• 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

35.47
/quisp/rules/RuleSetConverter/RuleSetConverter.cc
1
#include "RuleSetConverter.h"
2

3
#include <stdexcept>
4
#include <string>
5
#include <vector>
6

7
#include <omnetpp.h>
8

9
#include "runtime/Runtime.h"
10
#include "runtime/opcode.h"
11

12
namespace quisp::rules::rs_converter {
13

14
using runtime::InstructionTypes;
15

16
using namespace runtime;
17

18
RuleSet RuleSetConverter::construct(const RSData &data) {
×
19
  RuleSet rs;
×
20
  rs.id = data.ruleset_id;
×
21
  rs.owner_addr = data.owner_addr;
×
22
  auto &rules_data = data.rules;
×
23
  if (data.rules.size() == 0) throw omnetpp::cRuntimeError("empty ruleset");
×
24
  for (auto &rule_data : rules_data) {
×
25
    std::string name = rule_data->name + " with ";
×
26
    for (auto &interface : rule_data->qnic_interfaces) {
×
27
      name += std::to_string(interface.partner_addr) + "";
×
28
    }
×
29
    auto condition = constructCondition(rule_data->condition.get());
×
30
    auto action = constructAction(rule_data->action.get());
×
31
    auto terminate_condition = constructTerminateCondition(rule_data->condition.get());
×
32
    if (terminate_condition.opcodes.size() > 0) {
×
33
      rs.termination_condition = terminate_condition;
×
34
    }
×
35
    rs.rules.emplace_back(Rule{name, rule_data->send_tag, rule_data->receive_tag, condition, action});
×
36
  }
×
37
  return rs;
×
38
}
×
39

40
Program RuleSetConverter::constructTerminateCondition(const ConditionData *data) {
1✔
41
  if (data == nullptr) {
1✔
42
    return Program{"no terminate condition", {}};
×
43
  }
×
44
  auto opcodes = std::vector<InstructionTypes>{};
1✔
45
  std::string name;
1✔
46
  int i = 0;
1✔
47
  for (auto &clause_data : data->clauses) {
1✔
48
    i++;
1✔
49
    auto clause_ptr = clause_data.get();
1✔
50
    if (auto *c = dynamic_cast<const MeasureCountConditionClause *>(clause_ptr)) {
1✔
51
      /*
52
        LOAD count MemoryKey("count")
53
        BLT CONTINUE count max_count
54
        RET RS_TERMINATED
55
      CONTINUE:
56
        NOP
57
      */
58
      auto count = RegId::REG2;
1✔
59
      MemoryKey count_key{"measure_count" + std::to_string(i)};
1✔
60
      name += "MeasureCountCondition ";
1✔
61

62
      Label continue_label{std::string("CONTINUE_") + std::to_string(i)};
1✔
63
      opcodes.push_back(INSTR_LOAD_RegId_MemoryKey_{{count, count_key}});
1✔
64
      opcodes.push_back(INSTR_BLT_Label_RegId_int_{{continue_label, count, c->num_measure}});
1✔
65
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::RS_TERMINATED});
1✔
66
      opcodes.push_back(INSTR_NOP_None_{{None}, continue_label});
1✔
67
    }
1✔
68
  }
1✔
69
  return Program{name, opcodes};
1✔
70
}
1✔
71

72
Program RuleSetConverter::constructCondition(const ConditionData *data) {
3✔
73
  if (data == nullptr) {
3✔
74
    return Program{"no condition", {}};
×
75
  }
×
76
  auto opcodes = std::vector<InstructionTypes>{};
3✔
77
  std::string name;
3✔
78
  int i = 0;
3✔
79
  for (auto &clause_data : data->clauses) {
3✔
80
    i++;
3✔
81
    auto clause_ptr = clause_data.get();
3✔
82
    if (auto *c = dynamic_cast<const EnoughResourceConditionClause *>(clause_ptr)) {
3✔
83
      auto counter = RegId::REG0;
1✔
84
      auto qubit_id = RegId::REG1;
1✔
85

86
      Label loop_label{std::string("LOOP_") + std::to_string(i)};
1✔
87
      Label found_qubit_label{std::string("FOUND_QUBIT_") + std::to_string(i)};
1✔
88
      Label passed_label{std::string("PASSED_") + std::to_string(i)};
1✔
89
      /*
90
        SET qubit_id -1
91
        SET counter 0
92
      LOOP:
93
        INC qubit_id
94
        GET_QUBIT qubit_id partner_addr qubit_id
95
        BRANCH_IF_QUBIT_FOUND FOUND_QUBIT
96
        RET COND_FAILED
97
      FOUND_QUBIT:
98
        BRANCH_IF_LOCKED qubit_id LOOP
99
        INC counter
100
        BEQ counter num_resource_required PASSED
101
        JMP LOOP
102
      PASSED:
103
        RET COND_PASSED
104
      */
105
      opcodes.push_back(INSTR_SET_RegId_int_{{counter, 0}});
1✔
106
      opcodes.push_back(INSTR_SET_RegId_int_{{qubit_id, -1}});
1✔
107

108
      opcodes.push_back(INSTR_INC_RegId_{qubit_id, loop_label});
1✔
109
      opcodes.push_back(INSTR_GET_QUBIT_RegId_QNodeAddr_RegId_{{qubit_id, c->partner_address, qubit_id}});
1✔
110
      opcodes.push_back(INSTR_BRANCH_IF_QUBIT_FOUND_Label_{found_qubit_label});
1✔
111
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_FAILED});
1✔
112

113
      opcodes.push_back(INSTR_INC_RegId_{{counter}, found_qubit_label});
1✔
114

115
      opcodes.push_back(INSTR_BEQ_Label_RegId_int_{{passed_label, counter, c->num_resource}});
1✔
116
      opcodes.push_back(INSTR_JMP_Label_{loop_label});
1✔
117
      opcodes.push_back(INSTR_NOP_None_{nullptr, passed_label});
1✔
118

119
      name += "EnoughResource ";
1✔
120
    } else if (auto *c = dynamic_cast<const FidelityConditionClause *>(clause_ptr)) {
2✔
121
      // XXX: no impl in the original
122
      throw std::runtime_error("FidelityCondition has not implemented yet");
×
123
    } else if (auto *c = dynamic_cast<const PurificationCorrelationClause *>(clause_ptr)) {
2✔
124
      /*
125
        SET msg_index -1
126
        SET seq_no -1
127
        SET msg_count -1
128
        SET qubit_id -1
129
      LOOP:
130
        INC msg_index
131
        GET_MESSAGE_SEQ msg_index seq_no
132
        BRANCH_IF_MESSAGE_FOUND FOUND_MESSAGE
133
        RET COND_FAILED
134
      FOUND_MESSAGE:
135
        COUNT_MESSAGE seq_no msg_count
136
        BEQ FIND_QUBIT msg_count 2
137
        JMP LOOP
138
      FIND_QUBIT:
139
        GET_QUBIT_BY_SEQ_NO qubit_id partner_addr seq_no
140
        BRANCH_IF_QUBIT_FOUND FOUND_QUBIT
141
        JMP LOOP
142
      FOUND_QUBIT:
143
        STORE "purification_<shared_rule_tag>_seq_no" seq_no
144
        RET COND_PASSED
145
      */
146
      auto msg_index = RegId::REG0;
×
147
      auto seq_no = RegId::REG1;
×
148
      auto msg_count = RegId::REG2;
×
149
      auto qubit_id = RegId::REG3;
×
150
      MemoryKey key{"purification_" + std::to_string(c->shared_rule_tag) + "_seq_no"};
×
151

152
      Label loop_label{std::string("LOOP_") + std::to_string(i)};
×
153
      Label found_message_label{std::string("FOUND_MESSAGE_") + std::to_string(i)};
×
154
      Label find_qubit_label{std::string("FIND_QUBIT_") + std::to_string(i)};
×
155
      Label found_qubit_label{std::string("FOUND_QUBIT_") + std::to_string(i)};
×
156
      // variable init
157
      opcodes.push_back(INSTR_SET_RegId_int_{{msg_index, -1}});
×
158
      opcodes.push_back(INSTR_SET_RegId_int_{{seq_no, -1}});
×
159
      opcodes.push_back(INSTR_SET_RegId_int_{{msg_count, -1}});
×
160
      opcodes.push_back(INSTR_SET_RegId_int_{{qubit_id, -1}});
×
161
      // LOOP
162
      opcodes.push_back(INSTR_INC_RegId_{{msg_index}, {loop_label}});
×
163
      opcodes.push_back(INSTR_GET_MESSAGE_SEQ_RegId_RegId_{{seq_no, msg_index}});
×
164
      opcodes.push_back(INSTR_BRANCH_IF_MESSAGE_FOUND_Label_{found_message_label});
×
165
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_FAILED});
×
166
      // FOUND_MESSAGE
167
      opcodes.push_back(INSTR_COUNT_MESSAGE_RegId_RegId_{{msg_count, seq_no}, found_message_label});
×
168
      opcodes.push_back(INSTR_BEQ_Label_RegId_int_{{find_qubit_label, msg_count, 2}});
×
169
      opcodes.push_back(INSTR_JMP_Label_{loop_label});
×
170
      // FIND_QUBIT
171
      opcodes.push_back(INSTR_GET_QUBIT_BY_SEQ_NO_RegId_QNodeAddr_RegId_{{qubit_id, c->partner_address, seq_no}, find_qubit_label});
×
172
      opcodes.push_back(INSTR_BRANCH_IF_QUBIT_FOUND_Label_{found_qubit_label});
×
173
      opcodes.push_back(INSTR_JMP_Label_{loop_label});
×
174
      // FOUND_QUBIT
175
      opcodes.push_back(INSTR_STORE_MemoryKey_RegId_{{key, seq_no}, found_qubit_label});
×
176
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_PASSED});
×
177

178
      name += "PurificationCorrelation ";
×
179
    } else if (auto *c = dynamic_cast<const SwappingCorrectionClause *>(clause_ptr)) {
2✔
180
      /*
181
        SET msg_index -1
182
        SET seq_no -1
183
        SET msg_count -1
184
        SET qubit_id -1
185
      LOOP:
186
        INC msg_index
187
        GET_MESSAGE_SEQ msg_index seq_no
188
        BRANCH_IF_MESSAGE_FOUND FIND_QUBIT
189
        RET COND_FAILED
190
      FIND_QUBIT:
191
        GET_QUBIT_BY_SEQ_NO qubit_id partner_addr seq_no
192
        BRANCH_IF_QUBIT_FOUND FOUND_QUBIT
193
        JMP LOOP
194
      FOUND_QUBIT:
195
        STORE "swapping_<shared_rule_tag>_seq_no" seq_no
196
        RET COND_PASSED
197
      */
198
      auto msg_index = RegId::REG0;
×
199
      auto seq_no = RegId::REG1;
×
200
      auto msg_count = RegId::REG2;
×
201
      auto qubit_id = RegId::REG3;
×
202
      MemoryKey key{"swapping_" + std::to_string(c->shared_rule_tag) + "_seq_no"};
×
203

204
      Label loop_label{std::string("LOOP_") + std::to_string(i)};
×
205
      Label found_message_label{std::string("FOUND_MESSAGE_") + std::to_string(i)};
×
206
      Label find_qubit_label{std::string("FIND_QUBIT_") + std::to_string(i)};
×
207
      Label found_qubit_label{std::string("FOUND_QUBIT_") + std::to_string(i)};
×
208
      // variable init
209
      opcodes.push_back(INSTR_SET_RegId_int_{{msg_index, -1}});
×
210
      opcodes.push_back(INSTR_SET_RegId_int_{{seq_no, -1}});
×
211
      opcodes.push_back(INSTR_SET_RegId_int_{{msg_count, -1}});
×
212
      opcodes.push_back(INSTR_SET_RegId_int_{{qubit_id, -1}});
×
213
      // LOOP
214
      opcodes.push_back(INSTR_INC_RegId_{{msg_index}, {loop_label}});
×
215
      opcodes.push_back(INSTR_GET_MESSAGE_SEQ_RegId_RegId_{{seq_no, msg_index}});
×
216
      opcodes.push_back(INSTR_BRANCH_IF_MESSAGE_FOUND_Label_{find_qubit_label});
×
217
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_FAILED});
×
218
      // FIND_QUBIT
219
      opcodes.push_back(INSTR_GET_QUBIT_BY_SEQ_NO_RegId_QNodeAddr_RegId_{{qubit_id, c->partner_address, seq_no}, find_qubit_label});
×
220
      opcodes.push_back(INSTR_BRANCH_IF_QUBIT_FOUND_Label_{found_qubit_label});
×
221
      opcodes.push_back(INSTR_JMP_Label_{loop_label});
×
222
      // FOUND_QUBIT
223
      opcodes.push_back(INSTR_STORE_MemoryKey_RegId_{{key, seq_no}, found_qubit_label});
×
224
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_PASSED});
×
225

226
      name += "SwappingCorrection ";
×
227
    } else if (auto *c = dynamic_cast<const MeasureCountConditionClause *>(clause_ptr)) {
2✔
228
      /*
229
        LOAD count MemoryKey("count")
230
        BLT PASSED count max_count
231
        RET COND_FAILED
232
      PASSED:
233
        INC count
234
        STORE MemoryKey("count") count
235
        RET COND_PASSED
236
      */
237
      auto count = RegId::REG2;
2✔
238
      MemoryKey count_key{"measure_count" + std::to_string(i)};
2✔
239
      Label passed_label{std::string("PASSED_") + std::to_string(i)};
2✔
240
      opcodes.push_back(INSTR_LOAD_RegId_MemoryKey_{{count, count_key}});
2✔
241
      opcodes.push_back(INSTR_BLT_Label_RegId_int_{{passed_label, count, c->num_measure}});
2✔
242
      opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::COND_FAILED});
2✔
243
      opcodes.push_back(INSTR_INC_RegId_{count, passed_label});
2✔
244
      opcodes.push_back(INSTR_STORE_MemoryKey_RegId_{{count_key, count}});
2✔
245
      name += "MeasureCountCondition ";
2✔
246
    }
2✔
247
  }
3✔
248
  opcodes.push_back(INSTR_RET_ReturnCode_{{ReturnCode::COND_PASSED}});
3✔
249
  return Program{name, opcodes};
3✔
250
}
3✔
251

252
Program RuleSetConverter::constructAction(const ActionData *data) {
3✔
253
  if (auto *act = dynamic_cast<const Purification *>(data)) {
3✔
254
    return constructPurificationAction(act);
1✔
255
  }
1✔
256
  if (auto *act = dynamic_cast<const EntanglementSwapping *>(data)) {
2✔
257
    return constructEntanglementSwappingAction(act);
1✔
258
  }
1✔
259
  if (auto *act = dynamic_cast<const Tomography *>(data)) {
1✔
260
    return constructTomographyAction(act);
1✔
261
  }
1✔
262
  if (auto *act = dynamic_cast<const PurificationCorrelation *>(data)) {
×
263
    return constructPurificationCorrelationAction(act);
×
264
  }
×
265
  if (auto *act = dynamic_cast<const SwappingCorrection *>(data)) {
×
266
    return constructSwappingCorrectionAction(act);
×
267
  }
×
268

269
  throw std::runtime_error("got invalid actions");
×
270
  return Program{"empty", {}};
×
271
}
×
272

273
Program RuleSetConverter::constructEntanglementSwappingAction(const EntanglementSwapping *act) {
1✔
274
  /*
275
    qubit: q0, q1
276
    reg: pauli_op_left, pauli_op_right, seq_no
277
    key: "sent_swap_message_{shared_rule}"
278
  START
279
    SET pauli_op_left  0
280
    SET pauli_op_right 0
281
    SET seq_no 1
282
    LOAD seq_no "sent_swap_message_{shared_rule}" // if the key has not been set the value stays as is
283
    GET_QUBIT q0 left_partner  0
284
    GET_QUBIT q1 right_partner 0
285
    GATE_CNOT q0 q1
286
    MEASURE pauli_op_left 0 q0 x
287
    MEASURE pauli_op_left 1 q1 z
288
    FREE_QUBIT q0
289
    FREE_QUBIT q1
290
    SEND_SWAPPING_RESULT left_partner right_partner pauli_op_left  seq_no
291
    SEND_SWAPPING_RESULT right_partner left_partner pauli_op_right seq_no
292
    INC seq_no
293
    STORE "sent_swap_message_{shared_rule}" seq_no
294
  */
295
  auto left_interface = act->qnic_interfaces.at(0);
1✔
296
  auto right_interface = act->qnic_interfaces.at(1);
1✔
297
  QubitId q0{0};
1✔
298
  QubitId q1{1};
1✔
299
  QNodeAddr left_partner_addr{left_interface.partner_addr};
1✔
300
  QNodeAddr right_partner_addr{right_interface.partner_addr};
1✔
301
  RegId op_left = RegId::REG0;
1✔
302
  RegId op_right = RegId::REG1;
1✔
303
  RegId seq_no = RegId::REG2;
1✔
304
  MemoryKey seq_key{"sent_swap_message_" + std::to_string(act->shared_rule_tag)};
1✔
305

306
  std::vector<InstructionTypes> opcodes = {
1✔
307
      // clang-format off
308
    INSTR_SET_RegId_int_{{op_left, 0}},
1✔
309
    INSTR_SET_RegId_int_{{op_right, 0}},
1✔
310
    INSTR_SET_RegId_int_{{seq_no, 1}},
1✔
311
    INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_key}},
1✔
312
    INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{q0, left_partner_addr, 0}},
1✔
313
    INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{q1, right_partner_addr, 0}},
1✔
314
    INSTR_GATE_CNOT_QubitId_QubitId_{{q0, q1}},
1✔
315
    INSTR_MEASURE_RegId_int_QubitId_Basis_{{op_left, 0, q0, Basis::X}},
1✔
316
    INSTR_MEASURE_RegId_int_QubitId_Basis_{{op_left, 1, q1, Basis::Z}},
1✔
317
    INSTR_FREE_QUBIT_QubitId_{{q0}},
1✔
318
    INSTR_FREE_QUBIT_QubitId_{{q1}},
1✔
319
    INSTR_SEND_SWAPPING_RESULT_QNodeAddr_RegId_QNodeAddr_RegId_{{left_partner_addr, op_left, right_partner_addr, seq_no}},
1✔
320
    INSTR_SEND_SWAPPING_RESULT_QNodeAddr_RegId_QNodeAddr_RegId_{{right_partner_addr, op_right, left_partner_addr, seq_no}},
1✔
321
    INSTR_INC_RegId_{{seq_no}},
1✔
322
    INSTR_STORE_MemoryKey_RegId_{{seq_key, seq_no}}
1✔
323
      // clang-format on
324
  };
1✔
325
  return Program{
1✔
326
      "EntanglementSwapping",
1✔
327
      opcodes,
1✔
328
  };
1✔
329
}
1✔
330
Program RuleSetConverter::constructPurificationAction(const Purification *act) {
1✔
331
  auto pur_type = act->purification_type;
1✔
332
  if (pur_type == rules::PurType::SINGLE_X || pur_type == rules::PurType::SINGLE_Z || pur_type == rules::PurType::SINGLE_Y) {
1✔
333
    /*
334
      qubitId: qubit, trash_qubit
335
      Reg: result, seq_no // the sequence number of the qubit in the next rule
336
    START:
337
      SET seq_no 1 // sequence_number starts at 1
338
      LOAD seq_no "sent_purification_message_{shared_rule}" // if it has not been set the value stays as is
339
      GET_QUBIT qubit partner_addr 0
340
      GET_QUBIT trash_qubit partner_addr 1
341
      PURIFY_X/Y/Z result qubit trash_qubit // perform the circuit [0/1] as output
342
      PROMOTE qubit
343
      FREE_QUBIT trash_qubit // free the measured qubits
344
      SEND_PURIFICATION_RESULT partner_addr result seq_no
345
      INC seq_no
346
      STORE "sent_purificaiton_message_{shared_rule}" seq_no
347
    */
348
    QubitId qubit{0};
1✔
349
    QubitId trash_qubit{1};
1✔
350
    RegId measure_result = RegId::REG0;
1✔
351
    RegId seq_no = RegId::REG1;
1✔
352

353
    auto &interface = act->qnic_interfaces.at(0);
1✔
354
    QNodeAddr partner_addr{interface.partner_addr};
1✔
355
    MemoryKey seq_no_key{"sent_purification_message_" + std::to_string(act->shared_rule_tag)};
1✔
356

357
    std::string program_name;
1✔
358
    InstructionTypes purify_instruction = (InstructionTypes)INSTR_PURIFY_X_RegId_int_QubitId_QubitId_{{measure_result, 0, qubit, trash_qubit}};
1✔
359
    if (pur_type == rules::PurType::SINGLE_X) {
1✔
360
      purify_instruction = (InstructionTypes)INSTR_PURIFY_X_RegId_int_QubitId_QubitId_{{measure_result, 0, qubit, trash_qubit}};
1✔
361
      program_name = "X Purification";
1✔
362
    } else if (pur_type == rules::PurType::SINGLE_Y) {
1✔
363
      program_name = "Y Purification";
×
364
      purify_instruction = (InstructionTypes)INSTR_PURIFY_Y_RegId_int_QubitId_QubitId_{{measure_result, 0, qubit, trash_qubit}};
×
365
    } else {
×
366
      program_name = "Z Purification";
×
367
      purify_instruction = (InstructionTypes)INSTR_PURIFY_Z_RegId_int_QubitId_QubitId_{{measure_result, 0, qubit, trash_qubit}};
×
368
    }
×
369
    std::vector<InstructionTypes> opcodes{
1✔
370
        INSTR_SET_RegId_int_{{seq_no, 1}},
1✔
371
        INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_no_key}},
1✔
372
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{qubit, partner_addr, 0}},
1✔
373
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{trash_qubit, partner_addr, 1}},
1✔
374
        purify_instruction,
1✔
375
        INSTR_PROMOTE_QubitId_{{qubit}},
1✔
376
        INSTR_FREE_QUBIT_QubitId_{{trash_qubit}},
1✔
377
        INSTR_SEND_PURIFICATION_RESULT_QNodeAddr_RegId_RegId_PurType_{{partner_addr, measure_result, seq_no, pur_type}},
1✔
378
        INSTR_INC_RegId_{seq_no},
1✔
379
        INSTR_STORE_MemoryKey_RegId_{{seq_no_key, seq_no}},
1✔
380
    };
1✔
381
    return Program{program_name, opcodes};
1✔
382
  }
1✔
383

384
  // single selection double purification;
385
  // (i.e., reducing both X & Z errors but without checking error propagation from trash_qubits back to keep qubit)
386
  if (pur_type == rules::PurType::DOUBLE || pur_type == rules::PurType::DOUBLE_INV) {
×
387
    /*
388
      qubitId: qubit, trash_qubit_x, trash_qubit_z
389
      Reg: result, seq_no // the sequence number of the qubit in the next rule
390
    START:
391
      SET seq_no 1 // sequence_number starts at 1
392
      LOAD seq_no "sent_purification_message_{shared_rule}" // if it has not been set the value stays as is
393
      GET_QUBIT qubit partner_addr 0
394
      GET_QUBIT trash_qubit_x partner_addr 1
395
      GET_QUBIT trash_qubit_z partner_addr 2
396
      # if DOUBLE:
397
        PURIFY_X result 0 qubit trash_qubit_x
398
        PURIFY_Z result 1 qubit trash_qubit_z
399
      # else: // just change the order, no reason to also change the bitset index
400
        PURIFY_Z result 1 qubit trash_qubit_z
401
        PURIFY_X result 0 qubit trash_qubit_x
402
      PROMOTE qubit
403
      FREE_QUBIT trash_qubit_x
404
      FREE_QUBIT trash_qubit_z
405
      SEND_PURIFICATION_RESULT partner_addr result seq_no
406
      INC seq_no
407
      STORE "sent_purificaiton_message_{shared_rule}" seq_no
408
    */
409
    QubitId qubit{0};
×
410
    QubitId trash_qubit_x{1};
×
411
    QubitId trash_qubit_z{2};
×
412
    RegId measure_result = RegId::REG0;
×
413
    RegId seq_no = RegId::REG1;
×
414

415
    auto &interface = act->qnic_interfaces.at(0);
×
416
    QNodeAddr partner_addr{interface.partner_addr};
×
417
    MemoryKey seq_no_key{"sent_purification_message_" + std::to_string(act->shared_rule_tag)};
×
418

419
    std::string program_name = "Single Selection Double Purification XZ";
×
420
    InstructionTypes purify_instruction_1 = (InstructionTypes)INSTR_PURIFY_X_RegId_int_QubitId_QubitId_{{measure_result, 0, qubit, trash_qubit_x}};
×
421
    InstructionTypes purify_instruction_2 = (InstructionTypes)INSTR_PURIFY_Z_RegId_int_QubitId_QubitId_{{measure_result, 1, qubit, trash_qubit_z}};
×
422
    ;
×
423
    if (pur_type == rules::PurType::DOUBLE_INV) {
×
424
      program_name = "Single Selection Double Purification ZX (Inverse)";
×
425
      std::swap(purify_instruction_1, purify_instruction_2);
×
426
    }
×
427
    std::vector<InstructionTypes> opcodes{
×
428
        INSTR_SET_RegId_int_{{seq_no, 1}},
×
429
        INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_no_key}},
×
430
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{qubit, partner_addr, 0}},
×
431
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{trash_qubit_x, partner_addr, 1}},
×
432
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{trash_qubit_z, partner_addr, 2}},
×
433
        purify_instruction_1,
×
434
        purify_instruction_2,
×
435
        INSTR_PROMOTE_QubitId_{{qubit}},
×
436
        INSTR_FREE_QUBIT_QubitId_{{trash_qubit_x}},
×
437
        INSTR_FREE_QUBIT_QubitId_{{trash_qubit_z}},
×
438
        INSTR_SEND_PURIFICATION_RESULT_QNodeAddr_RegId_RegId_PurType_{{partner_addr, measure_result, seq_no, pur_type}},
×
439
        INSTR_INC_RegId_{seq_no},
×
440
        INSTR_STORE_MemoryKey_RegId_{{seq_no_key, seq_no}},
×
441
    };
×
442
    return Program{program_name, opcodes};
×
443
  }
×
444

445
  // https://arxiv.org/abs/0811.2639 (Fujii & Yamamoto double selection (single error) purification)
446
  // The naming is misleading,
447
  // TODO: change purification type naming
448
  // DSDA -> double selection X purification
449
  // DSDA_INV -> double selection Z purification
450
  if (pur_type == rules::PurType::DSSA || pur_type == rules::PurType::DSSA_INV) {
×
451
    /*
452
      qubitId: qubit, trash_qubit_z, trash_qubit_x
453
      Reg: result, seq_no // the sequence number of the qubit in the next rule
454
    START:
455
      SET seq_no 1 // sequence_number starts at 1
456
      LOAD seq_no "sent_purification_message_{shared_rule}" // if it has not been set the value stays as is
457
      GET_QUBIT qubit partner_addr 0
458
      GET_QUBIT trash_qubit_z partner_addr 1
459
      GET_QUBIT trash_qubit_x partner_addr 1
460
      # if DSSA (double selection X purification) :
461
        CNOT qubit trash_qubit_z
462
        CNOT trash_qubit_x trash_qubit_z
463
        MEASURE result 0 trash_qubit_z Z
464
        MEASURE result 1 trash_qubit_x X
465
      # if DSSA_INV (double selection Z purification):
466
        CNOT trash_qubit_x qubit
467
        CNOT trash_qubit_x trash_qubit_z
468
        MEASURE result 0 trash_qubit_z Z
469
        MEASURE result 1 trash_qubit_x X
470
      PROMOTE qubit
471
      FREE_QUBIT trash_qubit_z
472
      FREE_QUBIT trash_qubit_x
473
      SEND_PURIFICATION_RESULT partner_addr result seq_no
474
      INC seq_no
475
      STORE "sent_purificaiton_message_{shared_rule}" seq_no
476
    */
477
    QubitId qubit{0};
×
478
    QubitId trash_qubit_z{1};
×
479
    QubitId trash_qubit_x{2};
×
480
    RegId measure_result = RegId::REG0;
×
481
    RegId seq_no = RegId::REG1;
×
482

483
    auto &interface = act->qnic_interfaces.at(0);
×
484
    QNodeAddr partner_addr{interface.partner_addr};
×
485
    MemoryKey seq_no_key{"sent_purification_message_" + std::to_string(act->shared_rule_tag)};
×
486

487
    std::string program_name = "Double Selection Single Purification X";
×
488
    InstructionTypes first_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{qubit, trash_qubit_z}};
×
489
    if (pur_type == rules::PurType::DSSA_INV) {
×
490
      program_name = "Double Selection Single Purification Z";
×
491
      first_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{trash_qubit_x, qubit}};
×
492
    }
×
493
    std::vector<InstructionTypes> opcodes{
×
494
        INSTR_SET_RegId_int_{{seq_no, 1}},
×
495
        INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_no_key}},
×
496
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{qubit, partner_addr, 0}},
×
497
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{trash_qubit_z, partner_addr, 1}},
×
498
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{trash_qubit_x, partner_addr, 2}},
×
499
        first_cnot,
×
500
        INSTR_GATE_CNOT_QubitId_QubitId_{{trash_qubit_x, trash_qubit_z}},
×
501
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 0, trash_qubit_z, Basis::Z}},
×
502
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 1, trash_qubit_x, Basis::X}},
×
503
        INSTR_PROMOTE_QubitId_{{qubit}},
×
504
        INSTR_FREE_QUBIT_QubitId_{{trash_qubit_z}},
×
505
        INSTR_FREE_QUBIT_QubitId_{{trash_qubit_x}},
×
506
        INSTR_SEND_PURIFICATION_RESULT_QNodeAddr_RegId_RegId_PurType_{{partner_addr, measure_result, seq_no, pur_type}},
×
507
        INSTR_INC_RegId_{seq_no},
×
508
        INSTR_STORE_MemoryKey_RegId_{{seq_no_key, seq_no}},
×
509
    };
×
510
    return Program{program_name, opcodes};
×
511
  }
×
512

513
  if (pur_type == rules::PurType::DSDA_SECOND || pur_type == rules::PurType::DSDA_SECOND_INV) {
×
514
    /*
515
      qubitId: qubit, dssp_z, dssp_x, sssp_q;
516
      Reg: result, seq_no // the sequence number of the qubit in the next rule
517
    START:
518
      SET seq_no 1 // sequence_number starts at 1
519
      LOAD seq_no "sent_purification_message_{shared_rule}" // if it has not been set the value stays as is
520
      GET_QUBIT qubit partner_addr 0
521
      GET_QUBIT dssp_z partner_addr 1
522
      GET_QUBIT dssp_x partner_addr 2
523
      GET_QUBIT sssp_q  partner_addr 3
524
      # if DSDA_SECOND (double selection X purification -> single selection single purification Z) :
525
        CNOT qubit dssp_z               << diff
526
        CNOT dssp_x dssp_z
527
        CNOT sssp_q qubit               << diff
528
        MEASURE result 0 dssp_z Z
529
        MEASURE result 1 dssp_x X
530
        MEASURE result 2 sssp_q X       << diff
531
      # if DSDA_SECOND_INV (double selection Z purification -> double selection single purification X):
532
        CNOT dssp_x qubit               << diff
533
        CNOT dssp_x dssp_z
534
        CNOT qubit sssp_q               << diff
535
        MEASURE result 0 dssp_z Z
536
        MEASURE result 1 dssp_x X
537
        MEASURE result 2 sssp_q Z       << diff
538
      PROMOTE qubit
539
      FREE_QUBIT dssp_z
540
      FREE_QUBIT dssp_x
541
      FREE_QUBIT sssp_q
542
      SEND_PURIFICATION_RESULT partner_addr result seq_no
543
      INC seq_no
544
      STORE "sent_purificaiton_message_{shared_rule}" seq_no
545
    */
546
    QubitId qubit{0};
×
547
    QubitId dssp_z{1};
×
548
    QubitId dssp_x{2};
×
549
    QubitId sssp_q{3};
×
550
    RegId measure_result = RegId::REG0;
×
551
    RegId seq_no = RegId::REG1;
×
552

553
    auto &interface = act->qnic_interfaces.at(0);
×
554
    QNodeAddr partner_addr{interface.partner_addr};
×
555
    MemoryKey seq_no_key{"sent_purification_message_" + std::to_string(act->shared_rule_tag)};
×
556

557
    std::string program_name = "Ds-Sp X followed by Ss-Sp Z";
×
558
    InstructionTypes first_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{qubit, dssp_z}};
×
559
    InstructionTypes last_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{sssp_q, qubit}};
×
560
    InstructionTypes sssp_measure = (InstructionTypes)INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 2, sssp_q, Basis::X}};
×
561
    if (pur_type == rules::PurType::DSDA_SECOND_INV) {
×
562
      program_name = "Ds-Sp Z followed by Ss-Sp X";
×
563
      first_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{dssp_x, qubit}};
×
564
      last_cnot = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{qubit, sssp_q}};
×
565
      sssp_measure = (InstructionTypes)INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 2, sssp_q, Basis::Z}};
×
566
    }
×
567
    std::vector<InstructionTypes> opcodes{
×
568
        INSTR_SET_RegId_int_{{seq_no, 1}},
×
569
        INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_no_key}},
×
570
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{qubit, partner_addr, 0}},
×
571
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_z, partner_addr, 1}},
×
572
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_x, partner_addr, 2}},
×
573
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{sssp_q, partner_addr, 3}},
×
574
        first_cnot,
×
575
        INSTR_GATE_CNOT_QubitId_QubitId_{{dssp_x, dssp_z}},
×
576
        last_cnot,
×
577
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 0, dssp_z, Basis::Z}},
×
578
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 1, dssp_x, Basis::X}},
×
579
        sssp_measure,
×
580
        INSTR_PROMOTE_QubitId_{{qubit}},
×
581
        INSTR_FREE_QUBIT_QubitId_{{dssp_z}},
×
582
        INSTR_FREE_QUBIT_QubitId_{{dssp_x}},
×
583
        INSTR_FREE_QUBIT_QubitId_{{sssp_q}},
×
584
        INSTR_SEND_PURIFICATION_RESULT_QNodeAddr_RegId_RegId_PurType_{{partner_addr, measure_result, seq_no, pur_type}},
×
585
        INSTR_INC_RegId_{seq_no},
×
586
        INSTR_STORE_MemoryKey_RegId_{{seq_no_key, seq_no}},
×
587
    };
×
588
    return Program{program_name, opcodes};
×
589
  }
×
590

591
  if (pur_type == rules::PurType::DSDA || pur_type == rules::PurType::DSDA_INV) {
×
592
    /*
593
      qubitId: qubit, dssp_1_z, dssp_1_x, dssp_2_x, dssp_2_z;
594
      Reg: result, seq_no // the sequence number of the qubit in the next rule
595
    START:
596
      SET seq_no 1 // sequence_number starts at 1
597
      LOAD seq_no "sent_purification_message_{shared_rule}" // if it has not been set the value stays as is
598
      GET_QUBIT qubit partner_addr 0
599
      GET_QUBIT dssp_1_x partner_addr 1
600
      GET_QUBIT dssp_1_z partner_addr 2
601
      GET_QUBIT dssp_2_x partner_addr 3
602
      GET_QUBIT dssp_2_z partner_addr 4
603
      # if DSDA (double selection X purification -> double selection Z purification) :
604
        CNOT qubit dssp_1_z            << cnot_1
605
        CNOT dssp_1_x dssp_1_z         << cnot_2
606
        MEASURE result 0 dssp_1_z Z
607
        MEASURE result 1 dssp_1_x X
608

609
        CNOT dssp_2_x qubit            << cnot_3
610
        CNOT dssp_2_x dssp_2_z         << cnot_4
611
        MEASURE result 2 dssp_2_z Z
612
        MEASURE result 3 dssp_2_x X
613
      # if DSDA_INV (double selection Z purification -> double selection X purification):
614
        # measurement index stay the same for simplicity
615
        CNOT dssp_2_x qubit            << cnot_1
616
        CNOT dssp_2_x dssp_2_z         << cnot_2
617
        MEASURE result 2 dssp_2_z Z
618
        MEASURE result 3 dssp_2_x X
619

620
        CNOT qubit dssp_1_z            << cnot_3
621
        CNOT dssp_1_x dssp_1_z         << cnot_4
622
        MEASURE result 0 dssp_1_z Z
623
        MEASURE result 1 dssp_1_x X
624
      PROMOTE qubit
625
      FREE_QUBIT dssp_1_z
626
      FREE_QUBIT dssp_1_x
627
      FREE_QUBIT dssp_2_z
628
      FREE_QUBIT dssp_2_x
629
      SEND_PURIFICATION_RESULT partner_addr result seq_no
630
      INC seq_no
631
      STORE "sent_purificaiton_message_{shared_rule}" seq_no
632
    */
633
    QubitId qubit{0};
×
634
    QubitId dssp_1_z{1};
×
635
    QubitId dssp_1_x{2};
×
636
    QubitId dssp_2_z{3};
×
637
    QubitId dssp_2_x{4};
×
638
    RegId measure_result = RegId::REG0;
×
639
    RegId seq_no = RegId::REG1;
×
640

641
    auto &interface = act->qnic_interfaces.at(0);
×
642
    QNodeAddr partner_addr{interface.partner_addr};
×
643
    MemoryKey seq_no_key{"sent_purification_message_" + std::to_string(act->shared_rule_tag)};
×
644

645
    std::string program_name = "Ds-Sp X followed by Ds-Sp Z";
×
646
    InstructionTypes cnot_1 = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{qubit, dssp_1_z}};
×
647
    InstructionTypes cnot_2 = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{dssp_1_x, dssp_1_z}};
×
648
    InstructionTypes cnot_3 = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{dssp_2_x, qubit}};
×
649
    InstructionTypes cnot_4 = (InstructionTypes)INSTR_GATE_CNOT_QubitId_QubitId_{{dssp_2_x, dssp_2_z}};
×
650
    if (pur_type == rules::PurType::DSDA_SECOND) {
×
651
      program_name = "Ds-Sp Z followed by Ds-Sp Z";
×
652
      std::swap(cnot_1, cnot_3);
×
653
      std::swap(cnot_2, cnot_4);
×
654
    }
×
655
    std::vector<InstructionTypes> opcodes{
×
656
        INSTR_SET_RegId_int_{{seq_no, 1}},
×
657
        INSTR_LOAD_RegId_MemoryKey_{{seq_no, seq_no_key}},
×
658
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{qubit, partner_addr, 0}},
×
659
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_1_z, partner_addr, 1}},
×
660
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_1_x, partner_addr, 2}},
×
661
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_2_z, partner_addr, 3}},
×
662
        INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{dssp_2_x, partner_addr, 4}},
×
663
        cnot_1,
×
664
        cnot_2,
×
665
        cnot_3,
×
666
        cnot_4,
×
667
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 0, dssp_1_z, Basis::Z}},
×
668
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 1, dssp_1_x, Basis::X}},
×
669
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 3, dssp_2_z, Basis::Z}},
×
670
        INSTR_MEASURE_RegId_int_QubitId_Basis_{{measure_result, 4, dssp_2_x, Basis::X}},
×
671
        INSTR_PROMOTE_QubitId_{{qubit}},
×
672
        INSTR_FREE_QUBIT_QubitId_{{dssp_1_z}},
×
673
        INSTR_FREE_QUBIT_QubitId_{{dssp_1_x}},
×
674
        INSTR_FREE_QUBIT_QubitId_{{dssp_2_z}},
×
675
        INSTR_FREE_QUBIT_QubitId_{{dssp_2_x}},
×
676
        INSTR_SEND_PURIFICATION_RESULT_QNodeAddr_RegId_RegId_PurType_{{partner_addr, measure_result, seq_no, pur_type}},
×
677
        INSTR_INC_RegId_{seq_no},
×
678
        INSTR_STORE_MemoryKey_RegId_{{seq_no_key, seq_no}},
×
679
    };
×
680
    return Program{program_name, opcodes};
×
681
  };
×
682

683
  std::cout << const_cast<Purification *>(act)->serialize_json() << std::endl;
×
684
  throw std::runtime_error("pur not implemented");
×
685
  return Program{"Purification", {}};
×
686
}
×
687

688
Program RuleSetConverter::constructPurificationCorrelationAction(const PurificationCorrelation *act) {
×
689
  /*
690
    qubit_id: qubit
691
    Reg: seq_no, result_0, result_1
692
  START
693
    LOAD seq_no "purification_<shared_rule_tag>_seq_no"
694
    GET_QUBIT_BY_SEQ_NO q0 <partner_addr> seq
695
    GET_MESSAGE seq_no 0 result_0
696
    GET_MESSAGE seq_no 1 result_1
697
    DELETE_MESSAGE seq_no
698
    BEQ RESULT_MATCH result_0 result_1
699
    FREE_QUBIT q0
700
    RET NONE // result not match
701
  RESULT_MATCH:
702
    PROMOTE q0
703
  */
704
  // init
705
  QubitId qubit{0};
×
706
  auto seq_no = RegId::REG0;
×
707
  auto result_0 = RegId::REG1;
×
708
  auto result_1 = RegId::REG2;
×
709
  QNodeAddr partner_address = act->qnic_interfaces[0].partner_addr;
×
710
  MemoryKey key{"purification_" + std::to_string(act->shared_rule_tag) + "_seq_no"};
×
711
  // label
712
  Label result_match_label{"result_match"};
×
713
  Label result_not_match_label{"result_not_match"};
×
714
  // start of program
715
  std::vector<InstructionTypes> opcodes;
×
716
  opcodes.push_back(INSTR_LOAD_RegId_MemoryKey_{{seq_no, key}});
×
717
  opcodes.push_back(INSTR_GET_QUBIT_BY_SEQ_NO_QubitId_QNodeAddr_RegId_{{qubit, partner_address, seq_no}});
×
718
  opcodes.push_back(INSTR_GET_MESSAGE_RegId_RegId_int_{{result_0, seq_no, 0}});
×
719
  opcodes.push_back(INSTR_GET_MESSAGE_RegId_RegId_int_{{result_1, seq_no, 1}});
×
720
  opcodes.push_back(INSTR_DELETE_MESSAGE_RegId_{seq_no});
×
721
  opcodes.push_back(INSTR_BEQ_Label_RegId_RegId_{{result_match_label, result_0, result_1}});
×
722
  opcodes.push_back(INSTR_FREE_QUBIT_QubitId_{qubit});
×
723
  opcodes.push_back(INSTR_RET_ReturnCode_{ReturnCode::NONE});
×
724
  // RESULT MATCH
725
  opcodes.push_back(INSTR_PROMOTE_QubitId_{qubit, result_match_label});
×
726
  return Program{"PurificationCorrelation", opcodes};
×
727
}
×
728

729
Program RuleSetConverter::constructSwappingCorrectionAction(const SwappingCorrection *act) {
×
730
  /*
731
    qubit_id: qubit
732
    Reg: seq_no, pauli_op, new_partner_addr
733
  // start of the program
734
    LOAD seq_no "swapping_<shared_rule_tag>_seq_no"
735
    GET_QUBIT_BY_SEQ_NO q0 <partner_addr> seq
736
    GET_MESSAGE seq_no 0 pauli_op new_partner_addr
737
    DELETE_MESSAGE seq_no
738
    BEQ PAULI_Z pauli_op 1
739
    BEQ PAULI_X pauli_op 2
740
    BEQ PAULI_Y pauli_op 3
741
    JMP UPDATE_PARTER
742
  PAULI_Z
743
    GATE_Z qubit
744
    JMP UPDATE_PARTNER
745
  PAULI_X
746
    GATE_X qubit
747
    JMP UPDATE_PARTNER
748
  PAULI_Y
749
    GATE_Y qubit
750
  UPDATE_PARTNER
751
    PROMOTE qubit new_partner_addr
752
  */
753
  QubitId qubit{0};
×
754
  auto seq_no = RegId::REG0;
×
755
  auto pauli_op = RegId::REG1;
×
756
  auto new_partner_addr = RegId::REG2;
×
757
  QNodeAddr partner_address = act->qnic_interfaces[0].partner_addr;
×
758
  MemoryKey key{"swapping_" + std::to_string(act->shared_rule_tag) + "_seq_no"};
×
759
  // label
760
  Label pauli_x_label{"pauli_x"};
×
761
  Label pauli_y_label{"pauli_y"};
×
762
  Label pauli_z_label{"pauli_z"};
×
763
  Label update_partner_label{"update_partner"};
×
764
  // start of program
765
  std::vector<InstructionTypes> opcodes;
×
766
  opcodes.push_back(INSTR_LOAD_RegId_MemoryKey_{{seq_no, key}});
×
767
  opcodes.push_back(INSTR_GET_QUBIT_BY_SEQ_NO_QubitId_QNodeAddr_RegId_{{qubit, partner_address, seq_no}});
×
768
  opcodes.push_back(INSTR_GET_MESSAGE_RegId_RegId_RegId_int_{{pauli_op, new_partner_addr, seq_no, 0}});
×
769
  opcodes.push_back(INSTR_DELETE_MESSAGE_RegId_{seq_no});
×
770
  opcodes.push_back(INSTR_BEQ_Label_RegId_int_{{pauli_z_label, pauli_op, 1}});
×
771
  opcodes.push_back(INSTR_BEQ_Label_RegId_int_{{pauli_x_label, pauli_op, 2}});
×
772
  opcodes.push_back(INSTR_BEQ_Label_RegId_int_{{pauli_y_label, pauli_op, 3}});
×
773
  opcodes.push_back(INSTR_JMP_Label_{{update_partner_label}});
×
774
  // PAULI_Z
775
  opcodes.push_back(INSTR_GATE_Z_QubitId_{qubit, pauli_z_label});
×
776
  opcodes.push_back(INSTR_JMP_Label_{update_partner_label});
×
777
  // PAULI_X
778
  opcodes.push_back(INSTR_GATE_X_QubitId_{qubit, pauli_x_label});
×
779
  opcodes.push_back(INSTR_JMP_Label_{update_partner_label});
×
780
  // PAULI_Y
781
  opcodes.push_back(INSTR_GATE_Y_QubitId_{qubit, pauli_y_label});
×
782
  // UPDATE_PARTNER
783
  opcodes.push_back(INSTR_PROMOTE_QubitId_RegId_{{qubit, new_partner_addr}, update_partner_label});
×
784
  // END
785
  return Program{"SwappingCorrection", opcodes};
×
786
}
×
787

788
Program RuleSetConverter::constructTomographyAction(const Tomography *act) {
1✔
789
  /*
790
    LOAD count "count"
791
    GET_QUBIT q0 partner_addr qubit_resource_index
792
    BRANCH_IF_QUBIT_FOUND QUBIT_FOUND
793
    RET ERROR
794
  QUBIT_FOUND:
795
    MEASURE_RANDOM "outcome" q0
796
    INC count
797
    STORE "count" count
798
    FREE_QUBIT q0
799
    SEND_LINK_TOMOGRAPHY_RESULT partner_addr count "outcome" max_count
800
  */
801
  QubitId q0{0};
1✔
802
  MemoryKey outcome_key{"outcome"};
1✔
803
  MemoryKey count_key{"count"};
1✔
804
  Label qubit_found_label{"qubit_found"};
1✔
805
  auto count = RegId::REG0;
1✔
806
  int max_count = act->num_measurement;
1✔
807
  auto &qnic = act->qnic_interfaces.at(0);
1✔
808
  QNodeAddr partner_addr = qnic.partner_addr;
1✔
809
  auto qubit_resource_index = 0;
1✔
810
  simtime_t start_time = act->start_time;
1✔
811
  if (start_time == -1) {
1✔
812
    start_time = simTime();
1✔
813
  }
1✔
814
  return Program{
1✔
815
      "Tomography",
1✔
816
      {
1✔
817
          // clang-format off
818
  INSTR_LOAD_RegId_MemoryKey_{{count, count_key}},
1✔
819
  INSTR_GET_QUBIT_QubitId_QNodeAddr_int_{{q0, partner_addr, qubit_resource_index}},
1✔
820
  INSTR_BRANCH_IF_QUBIT_FOUND_Label_{qubit_found_label},
1✔
821
  INSTR_ERROR_String_{"Qubit not found for measurement"},
1✔
822
  INSTR_MEASURE_RANDOM_MemoryKey_QubitId_{{outcome_key, q0}, qubit_found_label},
1✔
823
  INSTR_INC_RegId_{count},
1✔
824
  INSTR_STORE_MemoryKey_RegId_{{count_key, count}},
1✔
825
  INSTR_FREE_QUBIT_QubitId_{q0},
1✔
826
  INSTR_SEND_LINK_TOMOGRAPHY_RESULT_QNodeAddr_RegId_MemoryKey_int_Time_{{partner_addr, count, outcome_key, max_count, start_time}}
1✔
827
          // clang-format on
828
      },
1✔
829
  };
1✔
830
}
1✔
831
}  // namespace quisp::rules::rs_converter
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