• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sfc-aqua / quisp / 4329255112

pending completion
4329255112

Pull #504

github

GitHub
Merge 948c96a03 into 3166d7e57
Pull Request #504: Integrate Message Exchange (Purification/Entanglement Swapping) into RuleSet and Runtime

957 of 957 new or added lines in 22 files covered. (100.0%)

2287 of 5806 relevant lines covered (39.39%)

46937.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.cc
1
/** \file BellStateAnalyzer.cc
2
 *
3
 *  \brief BellStateAnalyzer
4
 */
5
#include "BellStateAnalyzer.h"
6

7
#include <omnetpp/cexception.h>
8
#include <vector>
9

10
using namespace omnetpp;
11
using namespace quisp::messages;
12
using namespace quisp::physical::types;
13

14
namespace quisp::modules {
15

16
/** @class BellStateAnalyzer BellStateAnalyzer.cc
17
 *
18
 *  @brief BellStateAnalyzer
19
 */
20
Define_Module(BellStateAnalyzer);
21

22
BellStateAnalyzer::BellStateAnalyzer() : provider(utils::ComponentProvider{this}) {}
×
23

24
void BellStateAnalyzer::initialize() {
×
25
  state = BSAState::Idle;
×
26
  darkcount_probability = par("darkcount_probability").doubleValue();
×
27
  detection_efficiency = par("detection_efficiency").doubleValue();
×
28
  indistinguishability_window = par("indistinguishable_time_window").doubleValue();
×
29
  collection_efficiency = par("collection_efficiency").doubleValue();
×
30
  backend = provider.getQuantumBackend();
×
31
  validateProperties();
×
32
}
×
33

34
/**
35
 * @brief Handle the flying photonic qubits coming in to the BSA.
36
 * If the two photons arrive at the same time (within indistinguishable time window),
37
 * it will be entangled. We assume that we can distinguish between Psi+/- while
38
 * we cannot Phi+/- cannot be distinguished. Gate operations will be applied on the photons.
39
 *
40
 * @param msg must be of type PhotonicQubit message
41
 */
42
void BellStateAnalyzer::handleMessage(cMessage *msg) {
×
43
  auto photon = getPhotonRecordFromMessage(static_cast<PhotonicQubit *>(msg));
×
44
  delete msg;
×
45

46
  // clang-format off
47
  if ((state == BSAState::Idle && !photon.is_first) ||
×
48
      (state == BSAState::AcceptingFirstPort && photon.from_port == PortNumber::Second) ||
×
49
      (state == BSAState::AcceptingSecondPort && photon.from_port == PortNumber::First)) {
×
50
    discardPhoton(photon);
×
51
    return;
×
52
  }
×
53
  // clang-format on
54
  if (photon.is_first) {
×
55
    if (state == BSAState::Idle && photon.from_port == PortNumber::First) {
×
56
      state = BSAState::FirstPortArrive;
×
57
    } else if (state == BSAState::Idle && photon.from_port == PortNumber::Second) {
×
58
      state = BSAState::SecondPortArrive;
×
59
    } else if (state == BSAState::FirstPortArrive && photon.from_port == PortNumber::Second) {
×
60
      state = BSAState::Accepting;
×
61
      send(new CancelBSMTimeOutMsg(), "to_bsa_controller");
×
62
    } else if (state == BSAState::SecondPortArrive && photon.from_port == PortNumber::First) {
×
63
      state = BSAState::Accepting;
×
64
      send(new CancelBSMTimeOutMsg(), "to_bsa_controller");
×
65
    } else if (state == BSAState::AcceptingFirstPort && photon.from_port == PortNumber::First) {
×
66
      send(new CancelBSMTimeOutMsg(), "to_bsa_controller");
×
67
    } else if (state == BSAState::AcceptingSecondPort && photon.from_port == PortNumber::Second) {
×
68
      send(new CancelBSMTimeOutMsg(), "to_bsa_controller");
×
69
    } else {
×
70
      throw cRuntimeError("This should not happen; BSA state isn't set correctly.");
×
71
    }
×
72
  }
×
73

74
  if (photon.from_port == PortNumber::First)
×
75
    first_port_records.emplace_back(photon);
×
76
  else
×
77
    second_port_records.emplace_back(photon);
×
78

79
  if (!photon.is_last) {
×
80
    return;
×
81
  }
×
82

83
  if (state == BSAState::AcceptingFirstPort || state == BSAState::AcceptingSecondPort) {  // must be last photon
×
84
    state = BSAState::Idle;
×
85
    processPhotonRecords();
×
86
    return;
×
87
  }
×
88

89
  if (photon.from_port == PortNumber::First)
×
90
    state = BSAState::AcceptingSecondPort;
×
91
  else
×
92
    state = BSAState::AcceptingFirstPort;
×
93
}
×
94

95
void BellStateAnalyzer::processPhotonRecords() {
×
96
  auto *batch_click_msg = new BatchClickEvent();
×
97
  int number_of_possible_pairs = std::min(first_port_records.size(), second_port_records.size());
×
98
  for (int i = 0; i < number_of_possible_pairs; i++) {
×
99
    auto p = first_port_records[i];
×
100
    auto q = second_port_records[i];
×
101

102
    if (fabs(p.arrival_time - q.arrival_time) < indistinguishability_window) {
×
103
      batch_click_msg->appendClickResults(processIndistinguishPhotons(p, q));
×
104
    } else {
×
105
      batch_click_msg->appendClickResults({.success = false, .correction_operation = PauliOperator::I});
×
106
    }
×
107
  }
×
108
  first_port_records.clear();
×
109
  second_port_records.clear();
×
110
  send(batch_click_msg, "to_bsa_controller");
×
111
}
×
112

113
PhotonRecord BellStateAnalyzer::getPhotonRecordFromMessage(PhotonicQubit *photon_msg) {
×
114
  PhotonRecord photon{.qubit_ref = photon_msg->getQubitRefForUpdate(),
×
115
                      .arrival_time = photon_msg->getArrivalTime(),
×
116
                      .from_port = (photon_msg->arrivedOn("quantum_port$i", 0)) ? PortNumber::First : PortNumber::Second,
×
117
                      .is_lost = photon_msg->isLost(),
×
118
                      .is_first = photon_msg->isFirst(),
×
119
                      .is_last = photon_msg->isLast(),
×
120
                      .has_x_error = photon_msg->hasXError(),
×
121
                      .has_z_error = photon_msg->hasZError()};
×
122

123
  return photon;
×
124
}
×
125

126
BSAClickResult BellStateAnalyzer::processIndistinguishPhotons(PhotonRecord &p, PhotonRecord &q) {
×
127
  // although the photons get out of the fiber, we still need to roll the rng whether it will get collected by the detectors
128
  if (dblrand() > collection_efficiency) p.is_lost = true;
×
129
  if (dblrand() > collection_efficiency) q.is_lost = true;
×
130

131
  bool left_darkcount_click = dblrand() < darkcount_probability;
×
132
  bool right_darkcount_click = dblrand() < darkcount_probability;
×
133
  // false positive case
134
  if ((p.is_lost && left_darkcount_click && q.is_lost && right_darkcount_click) || (!p.is_lost && q.is_lost && right_darkcount_click) ||
×
135
      (p.is_lost && left_darkcount_click && !q.is_lost)) {
×
136
    discardPhoton(p);
×
137
    discardPhoton(q);
×
138
    // correction operation doesn't really matter but we still make it 50:50
139
    return {.success = true, .correction_operation = (dblrand() < 0.5) ? PauliOperator::X : PauliOperator::Y};
×
140
  }
×
141

142
  // we assume that only Psi+/- can de distinguished while we can't for Phi+/-
143
  bool isPsi = dblrand() < 0.5;
×
144
  bool left_click = dblrand() < detection_efficiency;
×
145
  bool right_click = dblrand() < detection_efficiency;
×
146
  if (!p.is_lost && !q.is_lost && isPsi && left_click && right_click) {
×
147
    bool isPsiPlus = dblrand() < 0.5;
×
148
    measureSuccessfully(p, q, isPsiPlus);
×
149
    return {.success = true, .correction_operation = isPsiPlus ? PauliOperator::X : PauliOperator::Y};
×
150
  }
×
151

152
  discardPhoton(p);
×
153
  discardPhoton(q);
×
154
  return {.success = false, .correction_operation = PauliOperator::I};
×
155
}
×
156

157
void BellStateAnalyzer::resetState() {
×
158
  state = BSAState::Idle;
×
159
  first_port_records.clear();
×
160
  second_port_records.clear();
×
161
}
×
162

163
void BellStateAnalyzer::validateProperties() {
×
164
  // currently we only allow 2 port BSA
165
  if (this->gateSize("quantum_port") != 2) {
×
166
    throw std::runtime_error("BellStateAnalyzer::parameter validation fail; BSA doesn't have 2 input quantum ports");
×
167
  }
×
168
  // validating parameters
169
  if (darkcount_probability < 0 || darkcount_probability > 1)
×
170
    throw std::runtime_error("BellStateAnalyzer::parameter validation fail; darkcount_probability does not in the [0, 1] range");
×
171
  if (detection_efficiency < 0 || detection_efficiency > 1)
×
172
    throw std::runtime_error("BellStateAnalyzer::parameter validation fail; detection_efficiency does not in the [0, 1] range");
×
173
  if (indistinguishability_window < 0) throw std::runtime_error("BellStateAnalyzer::parameter validation fail; indistinguishability_window cannot be lower than 0");
×
174
  if (collection_efficiency < 0 || collection_efficiency > 1)
×
175
    throw std::runtime_error("BellStateAnalyzer::parameter validation fail; collection_efficiency does not in the [0, 1] range");
×
176
}
×
177

178
void BellStateAnalyzer::measureSuccessfully(PhotonRecord &p, PhotonRecord &q, bool is_psi_plus) {
×
179
  auto p_ref = p.qubit_ref;
×
180
  auto q_ref = q.qubit_ref;
×
181

182
  if (p.has_x_error && p.has_z_error)
×
183
    y_error_count++;
×
184
  else if (p.has_x_error)
×
185
    x_error_count++;
×
186
  else if (p.has_z_error)
×
187
    z_error_count++;
×
188
  else
×
189
    no_error_count++;
×
190

191
  if (q.has_x_error && q.has_z_error)
×
192
    y_error_count++;
×
193
  else if (q.has_x_error)
×
194
    x_error_count++;
×
195
  else if (q.has_z_error)
×
196
    z_error_count++;
×
197
  else
×
198
    no_error_count++;
×
199

200
  p_ref->noiselessX();
×
201
  if (!is_psi_plus) {
×
202
    p_ref->noiselessZ();
×
203
  }
×
204
  p_ref->noiselessCNOT(q_ref);
×
205
  p_ref->noiselessMeasureX(backends::abstract::EigenvalueResult::PLUS_ONE);
×
206
  q_ref->noiselessMeasureZ(backends::abstract::EigenvalueResult::PLUS_ONE);
×
207
}
×
208

209
void BellStateAnalyzer::finish() {
×
210
  std::cout << "BSA Statistics (raw):\n";
×
211
  std::cout << "    " << no_error_count << ' ' << x_error_count << ' ' << y_error_count << ' ' << z_error_count << '\n';
×
212
}
×
213

214
void BellStateAnalyzer::discardPhoton(PhotonRecord &photon) { photon.qubit_ref->noiselessMeasureZ(); };
×
215

216
}  // namespace quisp::modules
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc