⚠️ LABORATOIRE ISOLÉ OBLIGATOIRE – Ce projet utilise des tensions électriques. Respectez les règles de sécurité. Toute expérimentation est sous votre responsabilité.
Quantum Analog Array Concept

Quantum Analog Array :
réseau d’oscillateurs couplés pour recuit analogique

Quantum Analog Array (QAA)
Machine de recuit analogique DIY

Construisez un réseau d’oscillateurs couplés, résolvez des problèmes d’optimisation (Max‑Cut, coloring, etc.) avec des composants de récupération.
Pas de cryogénie, pas de vide – seulement des amplis‑op, des résistances et un microcontrôleur.

🎯 Qu’est‑ce que le QAA ?

Le Quantum Analog Array (QAA) est une machine de recuit analogique inspirée des Coherent Ising Machines. Chaque “qubit analogique” est un oscillateur électronique dont la phase (\(0^\circ\) ou \(180^\circ\)) représente un spin binaire. Les oscillateurs sont couplés entre eux via des interactions qui reproduisent un Hamiltonien d’Ising :

\[ H = -\sum_{i

En laissant le système évoluer (recuit), il trouve spontanément une configuration de phases qui minimise l’énergie, ce qui correspond à la solution d’un problème d’optimisation combinatoire (Max‑Cut, coloration, factorisation, etc.).

Pourquoi c’est unique :
- Composants standard (ampli‑op, résistances, transistors) – récupérables dans de vieilles électroniques.
- Température ambiante, pas de cryostat.
- Modulaire : ajoutez des cartes pour passer de 4 à 16, 32 spins.
- Visualisation directe sur oscilloscope ou via microcontrôleur.
graph TD A[Problème combinatoire
Max‑Cut, TSP, ...] --> B[Mapping sur Hamiltonien d'Ising
matrice J, champs h] B --> C[Programmation du QAA
potentiomètres / multiplexeurs] C --> D[Recuit analogique
augmentation lente du gain] D --> E[Lecture des phases finales
solution du problème] style A fill:#00ff9d20 style B fill:#00ff9d20 style C fill:#00ff9d20 style D fill:#00ff9d20 style E fill:#ff336620

🛠️ 0. Avant de commencer

Outils nécessaires

Sécurité électrique

Alimentation symétrique à partir de deux piles 9V

Deux piles 9V en série : la jonction centrale = masse, les extrémités = +9V et -9V.
Ajoutez des condensateurs 100µF et 100nF pour filtrer.

🔧 1. Le qubit analogique : oscillateur à pont de Wien (et alternatives)

Pour un premier prototype, l’oscillateur à pont de Wien est simple. Il produit une sinusoïde pure dont l’amplitude est contrôlable par un potentiomètre.

Composants par oscillateur (pont de Wien) :
- 1 ampli‑op (ex. TL082)
- 2 résistances R = 10 kΩ
- 2 condensateurs C = 10 nF
- 1 potentiomètre 10 kΩ en série avec R2 (contrôle amplitude)
- 1 résistance de contre‑réaction Rf = 22 kΩ
- Alim symétrique ±5V à ±12V

Fréquence : f = 1/(2πRC) ≈ 1,6 kHz.

Limites : le pont de Wien nécessite un réglage précis du gain et est sensible au bruit. Pour des résultats plus robustes (et une sortie quasi‑binaire), utilisez des oscillateurs à relaxation (astable à 555) ou des ring oscillators CMOS. Le couplage se fait alors par injection de courant ou portes XOR.

Mesure de la phase

Un comparateur (LM339) transforme la sinusoïde en signal carré. En comparant avec une référence (oscillateur maître), on obtient le spin binaire (0° → +1, 180° → -1).

Sortie oscillateur → +IN comparateur
Référence (osc maître) → -IN comparateur
Sortie comparateur → GPIO (0 = phase 0°, 1 = phase 180°)

🔗 2. Couplage non‑linéaire (Ising) avec AD633 ou multiplier à transistors

L’interaction \(J_{ij} s_i s_j\) s’obtient en multipliant les signaux des deux oscillateurs et en injectant le résultat (avec un signe contrôlé).

Schéma AD633 :
- Sortie A → X1, sortie B → Y1
- W = (X1*Y1)/10 + Z (Z = masse)
- W injecté via R_c dans l'entrée de l'oscillateur A.
Pour J négatif (antiferro), soustraire le signal (buffer inverseur).

Alternative low‑cost : Multiplieur de Gilbert à deux transistors (récupération dans vieilles cartes radio).

Pointe technique 2026 : Les Ising machines récentes utilisent le sub‑harmonic injection locking (SHIL) pour binariser les phases. Un signal à 2f est injecté pour forcer les oscillateurs vers 0° ou 180°.

🧩 3. Module 4 qubits – BOM et architecture

Bill of Materials (estimatif récupération possible)

ComposantRéférenceQtéCoût neuf (€)
Ampli‑opTL084 (4 amplis)10,50
Résistances10k, 22k, etc.302
Condensateurs10nF, 100nF202
Potentiomètres10k (amplitude)42
ComparateursLM33910,30
MultiplicateursAD633 (ou fait maison)660 (ou 5)
CommutateursCD405121
MicrocontrôleurESP3215
Alim symétrique±12V (récupération)110

Total ~80€ neuf – bien moins avec de la récupération.

graph TD subgraph Module 4 qubits O1[Osc1] --phase--> C1[Comp1] O2[Osc2] --phase--> C2[Comp2] O3[Osc3] --phase--> C3[Comp3] O4[Osc4] --phase--> C4[Comp4] C1 & C2 & C3 & C4 --> uC[ESP32] uC -->|SPI / PWM| P1[Potis amplitude] uC -->|commande| MUX[CD4051 + AD633] MUX -->|signaux couplage| O1 & O2 & O3 & O4 end uC --> USB[PC / Affichage]

🌡️ 4. Protocole de recuit analogique automatisé

Le microcontrôleur exécute la séquence suivante (code fourni plus bas) :

  1. Amplitudes à zéro (oscillateurs éteints).
  2. Rampe linéaire d’amplitude sur annealSteps paliers (ex. 100).
  3. À chaque palier, attendre dwellTime ms.
  4. En fin de rampe, lire les phases des comparateurs.
  5. Répéter numRuns fois pour histogramme.

Recuit avancé : On peut aussi faire une rampe sur la force de couplage (démarrage fort puis décroissant) ou injecter du bruit PWM via une diode Zener.

🧮 5. Application : Max‑Cut sur un cycle C4

Problème : partitionner 4 sommets en deux groupes pour maximiser les arêtes coupées. Hamiltonien : \(H = - (s_1s_2 + s_2s_3 + s_3s_4 + s_4s_1)\). Les solutions sont 1010 et 0101.

Programmation des couplages : chaque arête correspond à un multiplicateur avec \(J=1\). Le recuit doit converger vers ces motifs.

💻 6. Simulateur web à phases continues (dynamique Kuramoto)

Ce simulateur reproduit la dynamique réelle d’oscillateurs couplés. Chaque oscillateur \(i\) a une phase \(\theta_i\) évoluant selon :

\[ \frac{d\theta_i}{dt} = \omega_i + \sum_j J_{ij} \sin(\theta_j - \theta_i) + \text{bruit} \]

Le spin binaire est \(s_i = \text{sign}(\cos \theta_i)\). L’énergie Ising est affichée en temps réel. Cliquez sur Lancer la simulation pour voir la convergence vers une configuration de phase (synchro/anti-synchro).

Énergie Ising : --

Spins : --

Remarque : Le modèle Kuramoto reproduit fidèlement la synchronisation progressive des oscillateurs. Observez comment les phases se verrouillent soit en phase (ferro) soit en opposition (antiferro) selon les couplages \(J_{ij}\).

📟 7. Firmware complet pour ESP32 / Arduino (4 qubits, extensible)

Le code ci‑dessous pilote les potentiomètres numériques (MCP41xxx), les multiplexeurs CD4051, lit les comparateurs et exécute le recuit automatique. Adaptez les broches selon votre montage. Ce firmware correspond exactement à celui que vous avez fourni, avec une structure claire et commentée.

#include <SPI.h>

#define NUM_QUBITS 4               // Nombre d'oscillateurs (max 8)
#define POT_CS     5               // Chip select pour MCP41xxx (SPI)
#define SPI_SCK    18
#define SPI_MOSI   23

int phasePins[NUM_QUBITS] = {32, 33, 25, 26};

#define MUX_ADDR_A 13
#define MUX_ADDR_B 12
#define MUX_ADDR_C 14
#define MUX_INHIBIT 27

struct Coupling {
  int i, j;            // indices des qubits (0..NUM_QUBITS-1)
  int muxChannel;      // canal du CD4051 (0..7) associé
  float strength;      // force du couplage (0..1)
};

Coupling couplings[] = {
  {0, 1, 0, 1.0},
  {1, 2, 1, 1.0},
  {2, 3, 2, 1.0},
  {3, 0, 3, 1.0}
};
int numCouplings = sizeof(couplings) / sizeof(couplings[0]);

int initialAmplitude = 0;       // 0 = amplitude minimale
int finalAmplitude   = 255;     // 255 = amplitude maximale
int annealSteps      = 100;     // nombre de paliers
int dwellTime        = 10;      // ms par palier
int numRuns          = 100;     // nombre de répétitions

void setPotentiometer(byte address, byte value) {
  digitalWrite(POT_CS, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(POT_CS, HIGH);
}

void setAmplitude(int qubit, int value) {
  // Supposons que chaque qubit a son propre potentiomètre MCP41xxx
  setPotentiometer(qubit, value);
}

void setCoupling(int channel, float strength) {
  // Active simplement le canal si strength > 0
  digitalWrite(MUX_INHIBIT, LOW);
  digitalWrite(MUX_ADDR_A, channel & 1);
  digitalWrite(MUX_ADDR_B, (channel >> 1) & 1);
  digitalWrite(MUX_ADDR_C, (channel >> 2) & 1);
  // Pour un réglage analogique, ajouter une PWM ici
}

void initHardware() {
  SPI.begin(SPI_SCK, -1, SPI_MOSI, POT_CS);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  pinMode(POT_CS, OUTPUT);
  digitalWrite(POT_CS, HIGH);

  for (int i = 0; i < NUM_QUBITS; i++) {
    pinMode(phasePins[i], INPUT);
    setAmplitude(i, initialAmplitude);
  }

  pinMode(MUX_ADDR_A, OUTPUT);
  pinMode(MUX_ADDR_B, OUTPUT);
  pinMode(MUX_ADDR_C, OUTPUT);
  pinMode(MUX_INHIBIT, OUTPUT);
  digitalWrite(MUX_INHIBIT, HIGH);  // désactive tous les couplages

  for (int c = 0; c < numCouplings; c++) {
    setCoupling(couplings[c].muxChannel, couplings[c].strength);
  }
}

uint8_t readPhases() {
  uint8_t state = 0;
  for (int i = 0; i < NUM_QUBITS; i++) {
    if (digitalRead(phasePins[i]) == HIGH) {
      state |= (1 << i);
    }
  }
  return state;
}

uint8_t anneal() {
  for (int i = 0; i < NUM_QUBITS; i++) {
    setAmplitude(i, 0);
  }
  delay(50);

  for (int step = 0; step <= annealSteps; step++) {
    int amp = map(step, 0, annealSteps, initialAmplitude, finalAmplitude);
    for (int i = 0; i < NUM_QUBITS; i++) {
      setAmplitude(i, amp);
    }
    delay(dwellTime);
  }

  return readPhases();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Quantum Analog Array Ready");
  initHardware();
  digitalWrite(MUX_INHIBIT, LOW);
}

void loop() {
  int histogram[1 << NUM_QUBITS] = {0};

  for (int run = 0; run < numRuns; run++) {
    uint8_t state = anneal();
    histogram[state]++;
    Serial.print("Run ");
    Serial.print(run);
    Serial.print(": state = ");
    for (int i = 0; i < NUM_QUBITS; i++) {
      Serial.print((state >> i) & 1);
    }
    Serial.println();
    delay(100);
  }

  Serial.println("\n=== Histogramme des résultats ===");
  for (int s = 0; s < (1 << NUM_QUBITS); s++) {
    if (histogram[s] > 0) {
      for (int i = 0; i < NUM_QUBITS; i++) Serial.print((s >> i) & 1);
      Serial.print(" : ");
      Serial.println(histogram[s]);
    }
  }
  Serial.println("Fin des tests");
  while(1);
}

Connexions typiques : Voir le tableau plus haut. Adaptez les broches SPI (CS, SCK, MOSI) et les entrées des comparateurs. Pour plus de qubits, chaînez des MCP41xxx avec CS distincts.

⚡ 8. Au‑delà du pont de Wien : oscillateurs non‑linéaires et SHIL

Pour des performances dignes des publications 2025‑2026, remplacez les oscillateurs sinusoïdaux par :

Le code fourni reste compatible avec ces variantes (seule la partie analogique change).

Références : Tsuchiya et al., JSSC 2025 ; Yamamoto et al., APL Photonics 2026.

🐞 9. Dépannage

📊 Comparatif : QAA vs autres approches

CritèreQAA (ce tuto)Simulateur logicielD‑WaveOrdinateur quantique
Coût50‑150€0€~15M$ (cloud)100M$+
TempératureAmbiante–15 mK10 mK
Évolutivité DIY4‑32 spinsillimité5000 qubits~1000 qubits

🎯 Conclusion

Vous avez désormais une feuille de route complète pour construire votre machine de recuit analogique. Le QAA est un outil pédagogique puissant, accessible et extensible. Partagez vos réalisations, améliorez le code et contribuez à l’open hardware !

Rappel : Utilisation uniquement à des fins éducatives. Respectez les réglementations locales.

➡️ Voir aussi l’introduction au calcul quantique (QuantumTam)