59int main(
int argc,
char** argv) {
60 std::cout <<
"[DEMO] Entanglement distribution (3 nodes) starting\n";
62 RngSeedManager::SetSeed(1);
63 RngSeedManager::SetRun(1);
66 cmd.Parse(argc, argv);
70 Trace(
"Entanglement Distribution with 3 nodes");
72 Time::SetResolution(Time::NS);
88 const Time kSingleGate = NanoSeconds(100);
89 const Time kTwoQGate = NanoSeconds(300);
90 const Time kQDelay = NanoSeconds(100);
91 const Time kClassical = kQDelay;
97 ch12->SetAttribute(
"Delay", TimeValue(kQDelay));
98 ch13->SetAttribute(
"Delay", TimeValue(kQDelay));
99 ch23->SetAttribute(
"Delay", TimeValue(kQDelay));
113 InternetStackHelper internet;
114 internet.Install(node1);
115 internet.Install(node2);
116 internet.Install(node3);
118 PointToPointHelper p2p;
119 p2p.SetDeviceAttribute(
"DataRate", StringValue(
"100Mbps"));
120 p2p.SetChannelAttribute(
"Delay", StringValue(
"100ns"));
122 Ipv4AddressHelper ipv4;
124 ipv4.SetBase(
"10.1.1.0",
"255.255.255.0");
125 auto ifs12 = ipv4.Assign(p2p.Install(node1, node2));
127 ipv4.SetBase(
"10.1.2.0",
"255.255.255.0");
128 auto ifs13 = ipv4.Assign(p2p.Install(node1, node3));
130 ipv4.SetBase(
"10.1.3.0",
"255.255.255.0");
131 auto ifs23 = ipv4.Assign(p2p.Install(node2, node3));
133 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
143 auto node1AckRx = Socket::CreateSocket(node1, UdpSocketFactory::GetTypeId());
144 node1AckRx->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kAckPort));
145 int node1AcksReceived = 0;
146 node1AckRx->SetRecvCallback([&](Ptr<Socket> sock) {
148 while (sock->RecvFrom(from)) {
150 TraceNodeText(
"Node1", StrCat(
"ACK received (", node1AcksReceived,
"/2 links confirmed)"));
151 std::cout <<
"[NODE1] ACK received (" << node1AcksReceived <<
"/2)\n";
152 if (node1AcksReceived == 2)
153 Trace(
"Node1: both Bell pair links confirmed");
158 auto node2AckRx = Socket::CreateSocket(node2, UdpSocketFactory::GetTypeId());
159 node2AckRx->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kAckPort));
160 node2AckRx->SetRecvCallback([&](Ptr<Socket> sock) {
162 while (sock->RecvFrom(from)) {
163 TraceNodeText(
"Node2",
"ACK from Node3: Bell pair 2 link confirmed");
164 Trace(
"Node2: Bell pair 2 confirmed by Node3");
165 std::cout <<
"[NODE2] ACK from Node3 received\n";
171 auto node2TxSock = Socket::CreateSocket(node2, UdpSocketFactory::GetTypeId());
172 node2TxSock->Connect(InetSocketAddress(ifs12.GetAddress(0),
kAckPort));
174 auto node3ToNode1Sock = Socket::CreateSocket(node3, UdpSocketFactory::GetTypeId());
175 node3ToNode1Sock->Connect(InetSocketAddress(ifs13.GetAddress(0),
kAckPort));
177 auto node3ToNode2Sock = Socket::CreateSocket(node3, UdpSocketFactory::GetTypeId());
178 node3ToNode2Sock->Connect(InetSocketAddress(ifs23.GetAddress(0),
kAckPort));
181 node2->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
182 TraceNodeText(
"Node2",
StrCat(
"Qubit ", q->GetLabel(),
" arrived - entangled with Node1"));
183 std::cout <<
"[NODE2] Qubit " << q->GetLabel() <<
" arrived\n";
184 node2TxSock->Send(Create<Packet>(1));
185 TraceSendPacket(
"Node2",
"Node1", Simulator::Now(), Simulator::Now() + kClassical,
186 StrCat(
"ACK: ", q->GetLabel(),
" received"),
"udp");
191 int node3QubitCount = 0;
192 node3->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
194 TraceNodeText(
"Node3",
StrCat(
"Qubit ", q->GetLabel(),
" arrived (", node3QubitCount,
"/2)"));
195 std::cout <<
"[NODE3] Qubit " << q->GetLabel() <<
" arrived\n";
196 if (node3QubitCount == 1) {
197 node3ToNode1Sock->Send(Create<Packet>(1));
198 TraceSendPacket(
"Node3",
"Node1", Simulator::Now(), Simulator::Now() + kClassical,
199 StrCat(
"ACK: ", q->GetLabel(),
" received"),
"udp");
201 node3ToNode2Sock->Send(Create<Packet>(1));
202 TraceSendPacket(
"Node3",
"Node2", Simulator::Now(), Simulator::Now() + kClassical,
203 StrCat(
"ACK: ", q->GetLabel(),
" received"),
"udp");
208 Simulator::Schedule(MicroSeconds(1), [&] {
209 Trace(
"Step 1: Node1 initializes Bell pair 0 (for Node2)");
212 auto q0a = node1->CreateQubit();
213 q0a->SetLabel(
"bell_0_a");
214 auto q0b = node1->CreateQubit();
215 q0b->SetLabel(
"bell_0_b");
221 Simulator::Schedule(kSingleGate, [=]() {
226 Simulator::Schedule(kTwoQGate, [=]() {
232 Simulator::Schedule(kSingleGate, [=]() {
233 auto t0 = Simulator::Now();
234 node1->Send(q0b, node2->GetId());
237 std::cout <<
"[STEP 1] Bell pair 0 sent: Node1 -> Node2\n";
245 Simulator::Schedule(MicroSeconds(3), [&] {
246 Trace(
"Step 2: Node1 initializes Bell pair 1 (for Node3)");
249 auto q1a = node1->CreateQubit();
250 q1a->SetLabel(
"bell_1_a");
251 auto q1b = node1->CreateQubit();
252 q1b->SetLabel(
"bell_1_b");
257 Simulator::Schedule(kSingleGate, [=]() {
261 Simulator::Schedule(kTwoQGate, [=]() {
266 Simulator::Schedule(kSingleGate, [=]() {
267 auto t0 = Simulator::Now();
268 node1->Send(q1b, node3->GetId());
271 std::cout <<
"[STEP 2] Bell pair 1 sent: Node1 -> Node3\n";
278 Simulator::Schedule(MicroSeconds(5), [&] {
279 Trace(
"Step 3: Node2 initializes Bell pair 2 (for Node3)");
282 auto q2a = node2->CreateQubit();
283 q2a->SetLabel(
"bell_2_a");
284 auto q2b = node2->CreateQubit();
285 q2b->SetLabel(
"bell_2_b");
290 Simulator::Schedule(kSingleGate, [=]() {
294 Simulator::Schedule(kTwoQGate, [=]() {
299 Simulator::Schedule(kSingleGate, [=]() {
300 auto t0 = Simulator::Now();
301 node2->Send(q2b, node3->GetId());
304 std::cout <<
"[STEP 3] Bell pair 2 sent: Node2 -> Node3\n";
311 Simulator::Schedule(MicroSeconds(20), [&] {
312 Trace(
"All pairwise Bell pairs established - 3 independent bipartite entangled links");
313 std::cout <<
"[DONE] All Bell pairs distributed\n";
316 Simulator::Stop(MilliSeconds(1));
318 Simulator::Destroy();
321 std::cout <<
"[DONE] Entanglement distribution finished\n";