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 TraceSetBitColor(
"q0",
"#44AA99");
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 == 2) {
170 TraceNodeText(
"Client2",
"Both outcomes received - q2 ready");
171 TraceSetBitColor(
"q2",
"#44AA99");
173 std::cout <<
"[CLIENT2] outcome m=" << m <<
" (" << c2OutcomesRxd <<
"/2) - q2\n";
177 auto c3RxSock = Socket::CreateSocket(client3, UdpSocketFactory::GetTypeId());
178 c3RxSock->Bind(InetSocketAddress(Ipv4Address::GetAny(),
kCtrlPort));
179 c3RxSock->SetRecvCallback([&](Ptr<Socket> sock) {
181 while (Ptr<Packet> p = sock->RecvFrom(from)) {
183 p->CopyData(&outcome, 1);
185 TraceNodeText(
"Client3", StrCat(
"q3 outcome m=", m,
" received - q4 ready"));
186 TraceSetBitColor(
"q4",
"#44AA99");
187 std::cout <<
"[CLIENT3] q3 outcome m=" << m <<
" - q4 ready\n";
193 auto orchToC1 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
194 orchToC1->Connect(InetSocketAddress(kClient1Addr,
kCtrlPort));
195 auto orchToC2 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
196 orchToC2->Connect(InetSocketAddress(kClient2Addr,
kCtrlPort));
197 auto orchToC3 = Socket::CreateSocket(orch, UdpSocketFactory::GetTypeId());
198 orchToC3->Connect(InetSocketAddress(kClient3Addr,
kCtrlPort));
203 client1->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
206 std::cout <<
"[CLIENT1] " << q->GetLabel() <<
" arrived\n";
208 client2->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
211 std::cout <<
"[CLIENT2] " << q->GetLabel() <<
" arrived\n";
213 client3->SetRecvCallback([&](std::shared_ptr<Qubit> q) {
216 std::cout <<
"[CLIENT3] " << q->GetLabel() <<
" arrived\n";
220 static const int kNumQubits = 5;
221 std::vector<std::shared_ptr<Qubit>> qubits;
226 Simulator::Schedule(MicroSeconds(1), [&] {
227 Trace(
"Orchestrator creates ", kNumQubits,
" qubits");
228 TraceNodeText(
"Orchestrator",
"Preparing 5-qubit linear cluster state");
229 for (
int i = 0; i < kNumQubits; ++i) {
230 auto q = orch->CreateQubit();
231 q->SetLabel(
"q" + std::to_string(i));
233 TraceCreateBit(
"Orchestrator", q->GetLabel(),
"quantum",
"#88CCEE");
237 Simulator::Schedule(kSingleGate, [&] {
238 Trace(
"Orchestrator applies H to all qubits");
239 TraceNodeText(
"Orchestrator",
"H layer (all qubits, parallel)");
240 for (
const auto& q : qubits) {
246 Simulator::Schedule(kTwoQGate, [&] {
247 Trace(
"CZ layer 1: CZ(q0,q1) CZ(q2,q3)");
250 TraceEntangle({qubits[0]->GetLabel(), qubits[1]->GetLabel()}, kTwoQGate);
252 TraceEntangle({qubits[2]->GetLabel(), qubits[3]->GetLabel()}, kTwoQGate);
255 Simulator::Schedule(kTwoQGate, [&] {
256 Trace(
"CZ layer 2: CZ(q1,q2) CZ(q3,q4) - cluster state ready");
257 TraceNodeText(
"Orchestrator",
"CZ layer 2 - cluster state ready");
259 TraceEntangle({qubits[1]->GetLabel(), qubits[2]->GetLabel()}, kTwoQGate);
261 TraceEntangle({qubits[3]->GetLabel(), qubits[4]->GetLabel()}, kTwoQGate);
264 Simulator::Schedule(kSingleGate, [&] {
265 Trace(
"Orchestrator sends q0, q2, q4 to clients");
266 TraceNodeText(
"Orchestrator",
"Sending q0/q2/q4 to clients");
267 orch->Send(qubits[0], client1->GetId());
268 orch->Send(qubits[2], client2->GetId());
269 orch->Send(qubits[4], client3->GetId());
271 auto t0 = Simulator::Now();
272 auto t1 = t0 + kQDelay;
273 TraceSendBit(
"q0",
"Orchestrator",
"Client1",
"quantum", t0, t1);
274 TraceSendBit(
"q2",
"Orchestrator",
"Client2",
"quantum", t0, t1);
275 TraceSendBit(
"q4",
"Orchestrator",
"Client3",
"quantum", t0, t1);
278 Simulator::Schedule(kQDelay + kSingleGate, [&] {
279 Trace(
"Orchestrator measures q1, q3 in X-basis");
283 auto m1 = orch->Measure(qubits[1], Basis::X);
284 Trace(
"q1 X-measure outcome = ",
m1);
289 auto m3 = orch->Measure(qubits[3], Basis::X);
290 Trace(
"q3 X-measure outcome = ", m3);
294 TraceNodeText(
"Orchestrator",
"Measurements complete - sending outcomes to clients");
295 const auto tNow = Simulator::Now();
297 uint8_t m1b = (uint8_t) (
m1 & 1);
298 uint8_t m3b = (uint8_t) (m3 & 1);
301 orchToC1->Send(Create<Packet>(&m1b, 1));
306 orchToC2->Send(Create<Packet>(&m1b, 1));
311 orchToC2->Send(Create<Packet>(&m3b, 1));
313 StrCat(
"q3 outcome: m=", m3));
316 orchToC3->Send(Create<Packet>(&m3b, 1));
318 StrCat(
"q3 outcome: m=", m3));
326 Simulator::Stop(MilliSeconds(1));
328 Simulator::Destroy();
331 std::cout <<
"[DONE] Distributed graph state generation finished\n";