56int main(
int argc,
char** argv) {
57 std::cout <<
"[DEMO] GHZ state distribution (4 nodes) starting\n";
59 RngSeedManager::SetSeed(1);
60 RngSeedManager::SetRun(1);
63 cmd.Parse(argc, argv);
68 Trace(
"GHZ State Distribution with 4 nodes");
70 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 ch14->SetAttribute(
"Delay", TimeValue(kQDelay));
110 InternetStackHelper internet;
111 internet.Install(node1);
112 internet.Install(node2);
113 internet.Install(node3);
114 internet.Install(node4);
116 PointToPointHelper p2p;
117 p2p.SetDeviceAttribute(
"DataRate", StringValue(
"100Mbps"));
118 p2p.SetChannelAttribute(
"Delay", StringValue(
"100ns"));
120 Ipv4AddressHelper ipv4;
122 ipv4.SetBase(
"10.1.1.0",
"255.255.255.0");
123 auto ifs12 = ipv4.Assign(p2p.Install(node1, node2));
125 ipv4.SetBase(
"10.1.2.0",
"255.255.255.0");
126 auto ifs13 = ipv4.Assign(p2p.Install(node1, node3));
128 ipv4.SetBase(
"10.1.3.0",
"255.255.255.0");
129 auto ifs14 = ipv4.Assign(p2p.Install(node1, node4));
131 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
140 const Ipv4Address kNode1Addr = ifs12.GetAddress(0);
143 auto node1AckRx = Socket::CreateSocket(node1, UdpSocketFactory::GetTypeId());
144 node1AckRx->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kAckPort));
145 int acksReceived = 0;
146 node1AckRx->SetRecvCallback([&](Ptr<Socket> sock) {
148 while (sock->RecvFrom(from)) {
150 TraceNodeText(
"Node1", StrCat(
"ACK received (", acksReceived,
"/3 GHZ nodes confirmed)"));
151 std::cout <<
"[NODE1] ACK " << acksReceived <<
"/3 received\n";
152 if (acksReceived == 3) {
153 Trace(
"GHZ resource confirmed by all remote nodes");
154 TraceSetBitColor(
"q0",
"#44AA99");
160 auto node2TxSock = Socket::CreateSocket(node2, UdpSocketFactory::GetTypeId());
161 node2TxSock->Connect(InetSocketAddress(kNode1Addr,
kAckPort));
163 auto node3TxSock = Socket::CreateSocket(node3, UdpSocketFactory::GetTypeId());
164 node3TxSock->Connect(InetSocketAddress(ifs13.GetAddress(0),
kAckPort));
166 auto node4TxSock = Socket::CreateSocket(node4, UdpSocketFactory::GetTypeId());
167 node4TxSock->Connect(InetSocketAddress(ifs14.GetAddress(0),
kAckPort));
170 node2->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
173 std::cout <<
"[NODE2] " << q->GetLabel() <<
" arrived\n";
174 node2TxSock->Send(Create<Packet>(1));
175 TraceSendPacket(
"Node2",
"Node1", Simulator::Now(), Simulator::Now() + kClassical,
176 StrCat(
"ACK: ", q->GetLabel(),
" received"));
180 node3->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
183 std::cout <<
"[NODE3] " << q->GetLabel() <<
" arrived\n";
184 node3TxSock->Send(Create<Packet>(1));
185 TraceSendPacket(
"Node3",
"Node1", Simulator::Now(), Simulator::Now() + kClassical,
186 StrCat(
"ACK: ", q->GetLabel(),
" received"));
190 node4->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
193 std::cout <<
"[NODE4] " << q->GetLabel() <<
" arrived\n";
194 node4TxSock->Send(Create<Packet>(1));
195 TraceSendPacket(
"Node4",
"Node1", Simulator::Now(), Simulator::Now() + kClassical,
196 StrCat(
"ACK: ", q->GetLabel(),
" received"));
202 Simulator::Schedule(MicroSeconds(1), [=] {
203 auto q0 = node1->CreateQubit(
"q0");
204 auto q1 = node1->CreateQubit(
"q1");
205 auto q2 = node1->CreateQubit(
"q2");
206 auto q3 = node1->CreateQubit(
"q3");
215 Simulator::Schedule(kSingleGate, [=] {
216 Trace(
"Applying H to q0");
221 Simulator::Schedule(kTwoQGate, [=] {
222 Trace(
"CNOT(q0, q1)");
227 Simulator::Schedule(kTwoQGate, [=] {
228 Trace(
"CNOT(q0, q2)");
233 Simulator::Schedule(kTwoQGate, [=] {
234 Trace(
"CNOT(q0, q3) - GHZ state ready");
238 std::cout <<
"[NODE1] GHZ state prepared: (|0000> + |1111>)/sqrt(2)\n";
243 Simulator::Schedule(kSingleGate, [=] {
244 Trace(
"Distributing GHZ qubits to nodes");
247 const Time kSendGap = NanoSeconds(50);
248 auto t0 = Simulator::Now();
250 node1->Send(q1, node2->GetId());
251 TraceSendBit(
"q1",
"Node1",
"Node2",
"quantum", t0, t0 + kQDelay);
253 Simulator::Schedule(kSendGap, [=] {
254 auto t1 = Simulator::Now();
255 node1->Send(q2, node3->GetId());
256 TraceSendBit(
"q2",
"Node1",
"Node3",
"quantum", t1, t1 + kQDelay);
258 Simulator::Schedule(kSendGap, [=] {
259 auto t2 = Simulator::Now();
260 node1->Send(q3, node4->GetId());
261 TraceSendBit(
"q3",
"Node1",
"Node4",
"quantum", t2, t2 + kQDelay);
262 TraceNodeText(
"Node1",
"q1/q2/q3 in transit - awaiting ACKs");
264 Simulator::Schedule(kQDelay + NanoSeconds(50), [=] {
265 Trace(
"GHZ quantum distribution complete - waiting for classical ACKs");
266 std::cout <<
"[NODE1] GHZ qubits in flight, waiting for ACKs\n";
277 Simulator::Stop(MilliSeconds(1));
279 Simulator::Destroy();
282 std::cout <<
"[DONE] GHZ distribution finished\n";