Q2NS dev
ns-3 module
Loading...
Searching...
No Matches
q2nsviz-teleportation-example.cc
Go to the documentation of this file.
1/*-----------------------------------------------------------------------------
2 * Q2NS - Quantum Network Simulator
3 * Copyright (c) 2026 quantuminternet.it
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *---------------------------------------------------------------------------*/
9/**
10 * @file q2nsviz-teleportation-example.cc
11 * @brief Quantum teleportation of a |+> state from Alice to Bob.
12 *
13 * Timing model (illustrative):
14 * kSingleGate = 100 ns (single-qubit gate)
15 * kTwoQGate = 300 ns (two-qubit gate)
16 * kQDelay = 10 ns (quantum channel propagation, ~2 m fiber)
17 *
18 * Visualization output is written to
19 * examples/example_traces/q2nsviz-teleportation-example.json and can be loaded in the
20 * q2nsviz viewer (src/q2ns/utils/q2nsviz-serve.sh).
21 *
22 * See docs/tutorials/tutorial-00.md for a detailed walkthrough.
23 */
24
25#include "ns3/core-module.h"
26#include "ns3/internet-module.h"
27#include "ns3/network-module.h"
28#include "ns3/point-to-point-module.h"
29#include "ns3/simulator.h"
30
31#include "ns3/q2ns-netcontroller.h"
32#include "ns3/q2ns-qgate.h"
33#include "ns3/q2ns-qnode.h"
34#include "ns3/q2ns-qubit.h"
35
36#include "ns3/q2nsviz-trace-writer.h"
37#include "ns3/q2nsviz-trace.h"
38
39#include <iostream>
40
41using namespace ns3;
42using namespace q2ns;
43
44static const uint16_t kCtrlPort = 9000;
45
46int main(int argc, char** argv) {
47 std::cout << "[DEMO] Quantum teleportation starting\n";
48
49 RngSeedManager::SetSeed(1);
50 RngSeedManager::SetRun(1);
51
52 CommandLine cmd;
53 cmd.Parse(argc, argv);
54
55 TraceWriter::Instance().Open("examples/example_traces/q2nsviz-teleportation-example.json");
56
57 Time::SetResolution(Time::NS);
58
59 // --- Create quantum network ---
60 NetController net;
61
62 auto alice = net.CreateNode();
63 auto bob = net.CreateNode();
64
65 // --- Timing constants ---
66 // Values are illustrative and platform-neutral (see file header for ranges).
67 const Time kSingleGate = NanoSeconds(100); // single-qubit gate
68 const Time kTwoQGate = NanoSeconds(300); // two-qubit gate
69 const Time kQDelay = NanoSeconds(10); // quantum link propagation (~2 m fiber)
70 const Time kClassical = kQDelay; // classical propagation = quantum (~2 m fiber)
71
72 // Quantum link: Alice <-> Bob
73 auto ch = net.InstallQuantumLink(alice, bob);
74 ch->SetAttribute("Delay", TimeValue(kQDelay));
75
76 TraceCreateNode("Alice", 25, 25);
77 TraceCreateNode("Bob", 75, 25);
78 TraceCreateChannel("Alice", "Bob", "quantum");
79
80 // --- Classical network (UDP for correction bits) ---
81 InternetStackHelper internet;
82 internet.Install(alice);
83 internet.Install(bob);
84
85 PointToPointHelper p2p;
86 p2p.SetDeviceAttribute("DataRate", StringValue("100Mbps"));
87 p2p.SetChannelAttribute("Delay", StringValue("10ns"));
88 NetDeviceContainer devices = p2p.Install(StaticCast<Node>(alice), StaticCast<Node>(bob));
89
90 Ipv4AddressHelper ip;
91 ip.SetBase("10.1.1.0", "255.255.255.0");
92 auto ifs = ip.Assign(devices);
93 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
94 TraceCreateChannel("Alice", "Bob", "classical");
95
96 // --- Sockets ---
97 Ptr<Socket> bobRxSocket = Socket::CreateSocket(bob, UdpSocketFactory::GetTypeId());
98 bobRxSocket->Bind(InetSocketAddress(Ipv4Address::GetAny(), kCtrlPort));
99
100 Ptr<Socket> aliceTxSocket = Socket::CreateSocket(alice, UdpSocketFactory::GetTypeId());
101 aliceTxSocket->Connect(InetSocketAddress(ifs.GetAddress(1), kCtrlPort));
102
103 // --- Bob's shared context (filled by quantum + classical callbacks) ---
104 struct BobCtx {
105 std::shared_ptr<Qubit> eprB;
106 bool qubitArrived = false;
107 bool bitsArrived = false;
108 int m1 = 0; // BSM bit 1: Z-correction coefficient
109 int m2 = 0; // BSM bit 2: X-correction coefficient
110 };
111 BobCtx bobCtx;
112
113 // Local helper: apply corrections and verify once both streams have arrived.
114 auto tryCorrections = [&]() {
115 if (!bobCtx.qubitArrived || !bobCtx.bitsArrived)
116 return;
117
118 Trace("Bob applies Pauli corrections Z^m", bobCtx.m1, " X^m", bobCtx.m2);
119
120 // Apply Z correction (if needed) as an explicit gate step
121 if (bobCtx.m1) {
122 bob->Apply(gates::Z(), {bobCtx.eprB});
123 TraceNodeText("Bob", "Z correction applied (m1=1)");
124 } else {
125 TraceNodeText("Bob", "Z correction skipped (m1=0)");
126 }
127
128 // Apply X correction (if needed) as an explicit gate step
129 if (bobCtx.m2) {
130 bob->Apply(gates::X(), {bobCtx.eprB});
131 TraceNodeText("Bob", "X correction applied (m2=1)");
132 } else {
133 TraceNodeText("Bob", "X correction skipped (m2=0)");
134 }
135
136 // Teleportation complete: bob_epr now holds the teleported psi state.
137 TraceSetBitColor("bob_epr", "#DDCC77");
138 TraceNodeText("Bob", "Teleportation complete - eprB holds psi state");
139
140 // Verify: |+> -> X-measurement should always yield 0
141 Trace("Bob verifies teleported state (X-basis)");
142 int mx = bob->Measure(bobCtx.eprB, Basis::X);
143 TraceMeasure("bob_epr", kSingleGate, "X");
144 TraceNodeText("Bob", StrCat("X-measure: ", mx, " (expected 0 -> |+> received)"));
145 std::cout << "[VERIFY] Bob's X-measure: " << mx << " (expected 0)\n";
146
147 Simulator::Stop();
148 };
149
150 // Bob's quantum receive callback: eprB has arrived from Alice.
151 bob->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
152 Trace("Bob receives eprB");
153 bobCtx.eprB = q;
154 bobCtx.qubitArrived = true;
155 TraceSetBitColor("bob_epr", "#117733");
156 TraceNodeText("Bob", "eprB arrived - half of Bell pair received");
157 std::cout << "[B][quantum] eprB arrived at t=" << Simulator::Now().GetNanoSeconds() << " ns\n";
158 tryCorrections();
159 });
160
161 // Bob's classical receive callback: correction bits have arrived from Alice.
162 bobRxSocket->SetRecvCallback([&](Ptr<Socket> sock) {
163 Address from;
164 while (Ptr<Packet> p = sock->RecvFrom(from)) {
165 uint8_t bits[2] = {0, 0};
166 p->CopyData(bits, 2);
167 bobCtx.m1 = bits[0] & 1;
168 bobCtx.m2 = bits[1] & 1;
169 bobCtx.bitsArrived = true;
170
171 Trace("Bob receives classical corrections m1=", bobCtx.m1, " m2=", bobCtx.m2);
172 TraceNodeText("Bob", StrCat("Corrections received: m1=", bobCtx.m1, " m2=", bobCtx.m2));
173 std::cout << "[B][CTRL] Corrections arrived: m1=" << bobCtx.m1 << " m2=" << bobCtx.m2 << "\n";
174 tryCorrections();
175 }
176 });
177
178 // ---------------------------------------------------------------------------
179 // Phase 1: Entanglement preparation and distribution
180 // ---------------------------------------------------------------------------
181 Simulator::Schedule(MicroSeconds(1), [&]() {
182 Trace("Phase 1: Alice creates eprA and eprB");
183 TraceNodeText("Alice", "Phase 1: preparing Bell pair");
184
185 auto eprA = alice->CreateQubit();
186 auto eprB = alice->CreateQubit();
187 TraceCreateBit("Alice", "alice_epr", "quantum", "#88CCEE");
188 TraceCreateBit("Alice", "bob_epr", "quantum", "#88CCEE");
189 std::cout << "[A] eprA, eprB created in |0>\n";
190
191 // H on eprA
192 Simulator::Schedule(kSingleGate, [&, eprA, eprB]() {
193 Trace("Alice applies H to eprA");
194 alice->Apply(gates::H(), {eprA});
195 TraceSetBitColor("alice_epr", "#bc71eb");
196 TraceNodeText("Alice", "H(eprA)");
197 std::cout << "[A] H applied to eprA\n";
198
199 // + 400 ns: CNOT(eprA, eprB) -> |Phi+>
200 Simulator::Schedule(kTwoQGate, [&, eprA, eprB]() {
201 Trace("Alice applies CNOT(eprA, eprB) -> Bell pair |Phi+>");
202 alice->Apply(gates::CNOT(), {eprA, eprB});
203 TraceEntangle({"alice_epr", "bob_epr"}, kTwoQGate);
204 TraceSetBitColor("alice_epr", "#117733");
205 TraceSetBitColor("bob_epr", "#117733");
206 TraceNodeText("Alice", "CNOT(eprA, eprB): Bell pair |Phi+> ready");
207 std::cout << "[A] Bell pair |Phi+> prepared\n";
208
209 // Send eprB to Bob
210 Simulator::Schedule(kSingleGate, [&, eprA, eprB]() {
211 Trace("Alice sends eprB to Bob");
212 TraceSendBit("bob_epr", "Alice", "Bob", "quantum", Simulator::Now(),
213 Simulator::Now() + kQDelay);
214 bool ok = alice->Send(eprB, bob->GetId());
215 TraceNodeText("Alice", "eprB sent - in transit to Bob (+10ns)");
216 std::cout << "[A][quantum] eprB sent: " << (ok ? "ok" : "failed") << "\n";
217 // eprA is retained at Alice for the BSM in Phase 2.
218
219 // ---------------------------------------------------------------
220 // Phase 2: Teleportation
221 // ---------------------------------------------------------------
222 Simulator::Schedule(MicroSeconds(2), [&, eprA]() { // absolute T = 3 us
223 Trace("Phase 2: Teleportation begins");
224 TraceNodeText("Alice", "Phase 2: teleportation (entanglement pre-shared)");
225
226 auto psi = alice->CreateQubit();
227 TraceCreateBit("Alice", "psi", "quantum", "#DDCC77");
228 std::cout << "[A] psi created in |0>\n";
229
230 // prepare |+> (the state to teleport)
231 Simulator::Schedule(kSingleGate, [&, eprA, psi]() {
232 Trace("Alice applies H to psi -> |+> (state to teleport)");
233 alice->Apply(gates::H(), {psi});
234 TraceSetBitColor("psi", "#DDCC77");
235 TraceNodeText("Alice", "H(psi): state to teleport is |+>");
236 std::cout << "[A] psi prepared as |+>\n";
237
238 // BSM step 1 - CNOT(psi, eprA)
239 Simulator::Schedule(kTwoQGate, [&, eprA, psi]() {
240 Trace("Alice BSM step 1: CNOT(psi, eprA)");
241 alice->Apply(gates::CNOT(), {psi, eprA});
242 TraceNodeText("Alice", "BSM step 1: CNOT(psi, eprA)");
243 std::cout << "[A][BSM] CNOT(psi, eprA) applied\n";
244
245 // BSM step 2 - H(psi)
246 Simulator::Schedule(kSingleGate, [&, eprA, psi]() {
247 Trace("Alice BSM step 2: H(psi)");
248 alice->Apply(gates::H(), {psi});
249 TraceNodeText("Alice", "BSM step 2: H(psi)");
250 std::cout << "[A][BSM] H(psi) applied\n";
251
252 // BSM step 3 - Z-measure psi and eprA
253 Simulator::Schedule(kSingleGate, [&, eprA, psi]() {
254 Trace("Alice BSM step 3: Z-measure psi and eprA");
255 TraceMeasure("psi", kSingleGate);
256 TraceMeasure("alice_epr", kSingleGate);
257
258 int m1 = alice->Measure(psi); // Z-basis -> Z correction at Bob
259 int m2 = alice->Measure(eprA); // Z-basis -> X correction at Bob
260
261 Trace("BSM outcome: m1=", m1, " m2=", m2);
262 TraceSetBitColor("psi", m1 == 0 ? "#FFFFFF" : "#000000");
263 TraceSetBitColor("alice_epr", m2 == 0 ? "#FFFFFF" : "#000000");
264 TraceNodeText("Alice", StrCat("BSM complete: m1=", m1, " m2=", m2));
265 std::cout << "[A][BSM] m1=" << m1 << " m2=" << m2 << "\n";
266
267 // Send classical corrections to Bob
268 uint8_t corrBits[2] = {(uint8_t) (m1 & 1), (uint8_t) (m2 & 1)};
269 aliceTxSocket->Send(Create<Packet>(corrBits, 2));
270 TraceSendPacket("Alice", "Bob", Simulator::Now(), Simulator::Now() + kClassical,
271 StrCat("Corrections m1=", m1, " m2=", m2));
272 TraceNodeText("Alice", StrCat("Corrections sent: m1=", m1, " m2=", m2));
273 std::cout << "[A][CTRL] Corrections sent (~5 us delay)\n";
274
275 // psi and eprA are consumed by measurement
276 TraceRemoveBit("psi");
277 TraceRemoveBit("alice_epr");
278 });
279 });
280 });
281 });
282 });
283 });
284 });
285 });
286 });
287
288 // --- Run simulation ---
289 Simulator::Stop(MilliSeconds(100));
290 Simulator::Run();
291 Simulator::Destroy();
292
294
295 std::cout << "[DONE] Quantum teleportation finished\n";
296 return 0;
297}
static TraceWriter & Instance()
void Open(const std::string &path)
Main user-facing facade for creating and configuring a quantum network.
ns3::Ptr< QNode > CreateNode(const std::string &label="")
Create a QNode with an optional human-readable label.
ns3::Ptr< QChannel > InstallQuantumLink(ns3::Ptr< QNode > a, ns3::Ptr< QNode > b)
Install a duplex quantum link between two nodes.
QGate X(ns3::Time d=ns3::Seconds(0))
Return the Pauli-X gate descriptor.
Definition q2ns-qgate.h:356
QGate H(ns3::Time d=ns3::Seconds(0))
Return the Hadamard gate descriptor.
Definition q2ns-qgate.h:383
QGate CNOT(ns3::Time d=ns3::Seconds(0))
Return the CNOT gate descriptor.
Definition q2ns-qgate.h:410
QGate Z(ns3::Time d=ns3::Seconds(0))
Return the Pauli-Z gate descriptor.
Definition q2ns-qgate.h:374
int main()
uint8_t m2
uint8_t m1
static const uint16_t kCtrlPort
std::string StrCat(Ts &&... parts)
void Trace(const std::string &text)
void TraceNodeText(const std::string &node, const std::string &text)
void TraceEntangle(const std::vector< std::string > &bits)
void TraceRemoveBit(const std::string &bitLabel, uint64_t t_ns=NowNs())
void TraceSendPacket(const std::string &from, const std::string &to, uint64_t t0_ns, uint64_t t1_ns, const std::string &label)
void TraceCreateBit(const std::string &node, const std::string &bitLabel, const std::string &kind, const std::string &color)
void TraceMeasure(const std::string &bitLabel, const std::string &base="Z")
void TraceCreateNode(const std::string &label, int xPct, int yPct)
void TraceCreateChannel(const std::string &from, const std::string &to, const std::string &kind)
void TraceSendBit(const std::string &bitLabel, const std::string &from, const std::string &to, const std::string &kind, uint64_t t0_ns, uint64_t t1_ns)
void TraceSetBitColor(const std::string &bitLabel, const std::string &color)