58int main(
int argc,
char** argv) {
59 std::cout <<
"[DEMO] Distributed graph state generation starting\n";
61 RngSeedManager::SetSeed(1);
62 RngSeedManager::SetRun(1);
65 cmd.Parse(argc, argv);
70 Time::SetResolution(Time::NS);
88 const Time kSingleGate = NanoSeconds(100);
89 const Time kTwoQGate = NanoSeconds(300);
90 const Time kQDelay = NanoSeconds(10);
91 const Time kClassical = kQDelay;
97 ch1->SetAttribute(
"Delay", TimeValue(kQDelay));
98 ch2->SetAttribute(
"Delay", TimeValue(kQDelay));
99 ch3->SetAttribute(
"Delay", TimeValue(kQDelay));
106 InternetStackHelper internet;
107 internet.Install(orch);
108 internet.Install(client1);
109 internet.Install(client2);
110 internet.Install(client3);
112 PointToPointHelper p2p;
113 p2p.SetDeviceAttribute(
"DataRate", StringValue(
"100Mbps"));
114 p2p.SetChannelAttribute(
"Delay", StringValue(
"10ns"));
116 auto dev1 = p2p.Install(orch, client1);
117 auto dev2 = p2p.Install(orch, client2);
118 auto dev3 = p2p.Install(orch, client3);
120 Ipv4AddressHelper ipv4;
121 ipv4.SetBase(
"10.1.1.0",
"255.255.255.0");
122 auto ifs1 = ipv4.Assign(dev1);
123 ipv4.SetBase(
"10.1.2.0",
"255.255.255.0");
124 auto ifs2 = ipv4.Assign(dev2);
125 ipv4.SetBase(
"10.1.3.0",
"255.255.255.0");
126 auto ifs3 = ipv4.Assign(dev3);
127 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
128 const Ipv4Address kClient1Addr = ifs1.GetAddress(1);
129 const Ipv4Address kClient2Addr = ifs2.GetAddress(1);
130 const Ipv4Address kClient3Addr = ifs3.GetAddress(1);
144 auto c1RxSock = Socket::CreateSocket(client1, UdpSocketFactory::GetTypeId());
145 c1RxSock->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kCtrlPort));
146 c1RxSock->SetRecvCallback([&](Ptr<Socket> sock) {
148 while (Ptr<Packet> p = sock->RecvFrom(from)) {
150 p->CopyData(&outcome, 1);
152 TraceNodeText(
"Client1", StrCat(
"q1 outcome m=", m,
" received - q0 ready"));
153 TraceRemoveCbit(
"m1");
154 std::cout <<
"[CLIENT1] q1 outcome m=" << m <<
" - q0 ready\n";
158 int c2OutcomesRxd = 0;
159 auto c2RxSock = Socket::CreateSocket(client2, UdpSocketFactory::GetTypeId());
160 c2RxSock->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kCtrlPort));
161 c2RxSock->SetRecvCallback([&](Ptr<Socket> sock) {
163 while (Ptr<Packet> p = sock->RecvFrom(from)) {
165 p->CopyData(&outcome, 1);
168 TraceNodeText(
"Client2", StrCat(
"outcome m=", m,
" received (", c2OutcomesRxd,
"/2)"));
169 if (c2OutcomesRxd == 1) {
170 TraceRemoveCbit(
"m1_c2");
172 TraceRemoveCbit(
"m3_c2");
173 TraceNodeText(
"Client2",
"Both outcomes received - q2 ready");
175 std::cout <<
"[CLIENT2] outcome m=" << m <<
" (" << c2OutcomesRxd <<
"/2) - q2\n";
179 auto c3RxSock = Socket::CreateSocket(client3, UdpSocketFactory::GetTypeId());
180 c3RxSock->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kCtrlPort));
181 c3RxSock->SetRecvCallback([&](Ptr<Socket> sock) {
183 while (Ptr<Packet> p = sock->RecvFrom(from)) {
185 p->CopyData(&outcome, 1);
187 TraceNodeText(
"Client3", StrCat(
"q3 outcome m=", m,
" received - q4 ready"));
188 TraceRemoveCbit(
"m3");
189 std::cout <<
"[CLIENT3] q3 outcome m=" << m <<
" - q4 ready\n";
195 auto orchToC1 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
196 orchToC1->Connect(InetSocketAddress(kClient1Addr,
kCtrlPort));
197 auto orchToC2 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
198 orchToC2->Connect(InetSocketAddress(kClient2Addr,
kCtrlPort));
199 auto orchToC3 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
200 orchToC3->Connect(InetSocketAddress(kClient3Addr,
kCtrlPort));
205 client1->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
207 std::cout <<
"[CLIENT1] " << q->GetLabel() <<
" arrived\n";
209 client2->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
211 std::cout <<
"[CLIENT2] " << q->GetLabel() <<
" arrived\n";
213 client3->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
215 std::cout <<
"[CLIENT3] " << q->GetLabel() <<
" arrived\n";
219 static const int kNumQubits = 5;
220 std::vector<std::shared_ptr<Qubit>> qubits;
225 Simulator::Schedule(MicroSeconds(1), [&] {
226 Trace(
"Orchestrator creates ", kNumQubits,
" qubits");
227 TraceNodeText(
"Orchestrator",
"Preparing 5-qubit linear cluster state");
228 for (
int i = 0; i < kNumQubits; ++i) {
229 auto q = orch->CreateQubit();
230 q->SetLabel(
"q" + std::to_string(i));
236 Simulator::Schedule(kSingleGate, [&] {
237 Trace(
"Orchestrator applies H to all qubits");
238 TraceNodeText(
"Orchestrator",
"H layer (all qubits, parallel)");
239 for (
const auto& q : qubits) {
244 Simulator::Schedule(kTwoQGate, [&] {
245 Trace(
"CZ layer 1: CZ(q0,q1) CZ(q2,q3)");
248 TraceEntangle({qubits[0]->GetLabel(), qubits[1]->GetLabel()}, kTwoQGate);
250 TraceEntangle({qubits[2]->GetLabel(), qubits[3]->GetLabel()}, kTwoQGate);
253 Simulator::Schedule(kTwoQGate, [&] {
254 Trace(
"CZ layer 2: CZ(q1,q2) CZ(q3,q4) - cluster state ready");
255 TraceNodeText(
"Orchestrator",
"CZ layer 2 - cluster state ready");
257 TraceEntangle({qubits[1]->GetLabel(), qubits[2]->GetLabel()}, kTwoQGate);
259 TraceEntangle({qubits[3]->GetLabel(), qubits[4]->GetLabel()}, kTwoQGate);
262 Simulator::Schedule(kSingleGate, [&] {
263 Trace(
"Orchestrator sends q0, q2, q4 to clients");
264 TraceNodeText(
"Orchestrator",
"Sending q0/q2/q4 to clients");
265 orch->Send(qubits[0], client1->GetId());
266 orch->Send(qubits[2], client2->GetId());
267 orch->Send(qubits[4], client3->GetId());
269 auto t0 = Simulator::Now();
270 auto t1 = t0 + kQDelay;
276 Simulator::Schedule(kQDelay + kSingleGate, [&] {
277 Trace(
"Orchestrator measures q1, q3 in X-basis");
281 auto m1 = orch->Measure(qubits[1], Basis::X);
282 Trace(
"q1 X-measure outcome = ",
m1);
287 auto m3 = orch->Measure(qubits[3], Basis::X);
288 Trace(
"q3 X-measure outcome = ", m3);
292 TraceNodeText(
"Orchestrator",
"Measurements complete - sending outcomes to clients");
293 const auto tNow = Simulator::Now();
295 uint8_t m1b = (uint8_t) (
m1 & 1);
296 uint8_t m3b = (uint8_t) (m3 & 1);
304 orchToC1->Send(Create<Packet>(&m1b, 1));
305 TraceSendCbit(
"m1",
"Orchestrator",
"Client1", tNow, tNow + kClassical);
307 StrCat(
"q1 outcome: m=",
m1),
"udp");
310 orchToC2->Send(Create<Packet>(&m1b, 1));
311 TraceSendCbit(
"m1_c2",
"Orchestrator",
"Client2", tNow, tNow + kClassical);
313 StrCat(
"q1 outcome: m=",
m1),
"udp");
316 orchToC2->Send(Create<Packet>(&m3b, 1));
317 TraceSendCbit(
"m3_c2",
"Orchestrator",
"Client2", tNow, tNow + kClassical);
319 StrCat(
"q3 outcome: m=", m3),
"udp");
322 orchToC3->Send(Create<Packet>(&m3b, 1));
323 TraceSendCbit(
"m3",
"Orchestrator",
"Client3", tNow, tNow + kClassical);
325 StrCat(
"q3 outcome: m=", m3),
"udp");
333 Simulator::Stop(MilliSeconds(1));
335 Simulator::Destroy();
338 std::cout <<
"[DONE] Distributed graph state generation finished\n";