Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
SimpleOps.h
Go to the documentation of this file.
1
13#pragma once
14
15#ifndef _SIMPLEOPS_H_
16#define _SIMPLEOPS_H_
17
18#include <cctype>
19#include <limits>
20#include <string_view>
21
22#include "Expr.h"
23
24namespace qasm {
25// something like this id[value] used for example by qreg and creg declarations
26// also when a qubit or cbit is referenced
28 public:
29 IndexedId() : index(0) {}
30 IndexedId(const std::string &id, int index) : id(id), index(index) {}
31
33
34 double Eval() const { return index; }
35
36 operator std::string() const {
37 return declType + " " + id + "[" + std::to_string(index) + "]";
38 }
39
40 std::string id;
41 int index;
42 int base = 0; // to be used when allocating the qubits/cbits in the circuit
43 std::string declType; // "qreg" or "creg" or "id"
44};
45
47
48using DeclarationRegistry = std::unordered_map<std::string, DeclarationKind>;
49
50inline std::string_view DeclarationKindName(DeclarationKind kind) {
51 switch (kind) {
53 return "quantum register";
55 return "classical register";
57 return "input";
59 return "gate";
61 return "opaque gate";
62 }
63
64 return "declaration";
65}
66
67inline void RegisterDeclaration(DeclarationRegistry &declarations,
68 const std::string &name, DeclarationKind kind) {
69 const auto [it, inserted] = declarations.emplace(name, kind);
70 if (inserted) return;
71
72 if (it->second == kind)
73 throw std::invalid_argument("Duplicate declaration of '" + name + "'.");
74
75 throw std::invalid_argument(
76 "Declaration of '" + name + "' conflicts with an existing " +
77 std::string(DeclarationKindName(it->second)) + ".");
78}
79
80inline int ValidateRegisterAllocation(const IndexedId &id, int currentSize,
81 std::string_view kind) {
82 const int size = id.index;
83 if (size <= 0)
84 throw std::invalid_argument(std::string(kind) + " register '" + id.id +
85 "' must have a positive size.");
86
87 if (currentSize < 0 || currentSize > std::numeric_limits<int>::max() - size)
88 throw std::overflow_error(std::string(kind) +
89 " register allocation exceeds supported "
90 "maximum.");
91
92 return size;
93}
94
96 template <typename, typename>
97 struct result {
98 typedef IndexedId type;
99 };
100
101 template <typename ID, typename IND>
102 IndexedId operator()(const ID &id, IND index) const {
103 return IndexedId(id, index);
104 }
105};
106
107inline phx::function<MakeIndexedIdExpression> MakeIndexedId;
108
109using SimpleExpType = std::variant<double, int, std::string>;
110
111using ArgumentType = std::variant<std::string, IndexedId>;
112using RegisterMap = std::unordered_map<std::string, IndexedId>;
113using MixedListType = std::vector<ArgumentType>;
115 boost::fusion::vector<std::string, boost::optional<int>, std::string>;
116
117inline std::vector<int> ResolveRegisterOperand(const ArgumentType &argument,
118 const RegisterMap &registers,
119 std::string_view kind) {
120 const std::string &name = std::holds_alternative<IndexedId>(argument)
121 ? std::get<IndexedId>(argument).id
122 : std::get<std::string>(argument);
123 const auto it = registers.find(name);
124 if (it == registers.end())
125 throw std::invalid_argument("Undeclared " + std::string(kind) +
126 " register '" + name + "'.");
127
128 const IndexedId &declaration = it->second;
129 if (std::holds_alternative<IndexedId>(argument)) {
130 const int index = std::get<IndexedId>(argument).index;
131 if (index < 0 || index >= declaration.index) {
132 std::string titledKind(kind);
133 titledKind[0] = static_cast<char>(
134 std::toupper(static_cast<unsigned char>(titledKind[0])));
135 throw std::out_of_range(titledKind + " register '" + name + "' index " +
136 std::to_string(index) + " is out of range [0, " +
137 std::to_string(declaration.index) + ").");
138 }
139
140 return {declaration.base + index};
141 }
142
143 std::vector<int> resolved;
144 resolved.reserve(static_cast<size_t>(declaration.index));
145 for (int index = 0; index < declaration.index; ++index)
146 resolved.push_back(declaration.base + index);
147 return resolved;
148}
149
150inline void RequireMatchingRegisterWidths(const std::vector<int> &left,
151 const std::vector<int> &right,
152 std::string_view operation) {
153 if (left.size() != right.size())
154 throw std::invalid_argument(std::string(operation) +
155 " operands must have the same width.");
156}
157
158using SimpleGatecallType = boost::fusion::vector<std::string, MixedListType>;
160 boost::fusion::vector<std::string, std::vector<Expression>, MixedListType>;
161using GatecallType = std::variant<SimpleGatecallType, ExpGatecallType>;
162
164 boost::fusion::vector<std::vector<Expression>, ArgumentType>;
165using CXGateCallType = boost::fusion::vector<ArgumentType, ArgumentType>;
166
167using UopType = std::variant<UGateCallType, CXGateCallType, GatecallType>;
168
169// QASM3 call-site gate modifiers: `ctrl @`, `negctrl @`, `inv @` and
170// `pow(k) @`.
171enum class ModifierKind { Ctrl, NegCtrl, Inv, Pow };
172
174 ModifierType() = default;
177
179 double exponent = 0.; // only meaningful for ModifierKind::Pow
180 // The optional control count of `ctrl(n) @` / `negctrl(n) @`; 1 for the
181 // countless spelling and for every non-control modifier. Kept on the
182 // modifier instead of expanded into n separate ModifierType entries so that
183 // one parsed modifier remains one element of ModifierListType - the list's
184 // source order is what tells AddModifiedGateExpr which qubit arguments a
185 // control owns.
186 int count = 1;
187};
188
189// Modifiers are kept in source order, i.e. outermost first: in
190// `ctrl @ inv @ s q[0], q[1]` the control is applied last, to the inverted
191// gate, and it consumes the first qubit argument.
192using ModifierListType = std::vector<ModifierType>;
193using ModifiedUopType = boost::fusion::vector<ModifierListType, UopType>;
194
196 template <typename, typename>
197 struct result {
199 };
200
201 // `variables` carries the top-level `input` bindings (threaded from the
202 // `powMod` rule via std::ref(inputValues), the same grammar member
203 // AddModifiedGate's call site uses), so `pow(theta) @ x q[0];` resolves
204 // theta the same way an ordinary gate parameter does. A modified call
205 // cannot appear inside a gate declaration body, so no macro formal
206 // parameter is ever in scope here - any identifier absent from `variables`
207 // is still an error (Variable::Eval throws), not a silent zero.
208 template <typename E, typename V>
209 ModifierType operator()(const E &exponent, const V &variables) const {
210 return ModifierType(ModifierKind::Pow, exponent.Eval(variables));
211 }
212};
213
214inline phx::function<MakePowModifierExpression> MakePowModifier;
215
216// Builds a `ctrl @` / `negctrl @` modifier, with the optional control count
217// of `ctrl(n) @`. `count` is absent for the countless spelling, in which case
218// it is 1 - so `ctrl(1) @ g` and `ctrl @ g` produce identical modifiers.
219//
220// `variables` is threaded exactly as MakePowModifierExpression's is, so
221// `ctrl(n) @` may name a top-level `input`; an identifier absent from it is
222// an error via Variable::Eval rather than a silent zero. A count that is not
223// a positive whole number is rejected here, where the spelling is still
224// known. How many controls the lowering can actually realise is not decided
225// here - that stays in AddModifiedGateExpr, which already reports it.
227 template <typename, typename, typename>
228 struct result {
230 };
231
232 template <typename K, typename E, typename V>
233 ModifierType operator()(K kind, const E &count, const V &variables) const {
234 if (!count) return ModifierType(kind);
235
236 const double value = count->Eval(variables);
237 if (!std::isfinite(value))
238 throw std::invalid_argument(
239 "The control count of ctrl(n) @ / negctrl(n) @ must be finite, "
240 "got: " +
241 std::to_string(value));
242
243 const double rounded = std::round(value);
244
245 if (std::abs(value - rounded) > 1e-9 || rounded < 1. || rounded > 64.)
246 throw std::invalid_argument(
247 "The control count of ctrl(n) @ / negctrl(n) @ must be a positive "
248 "whole number, got: " +
249 std::to_string(value));
250
251 return ModifierType(kind, 0., static_cast<int>(rounded));
252 }
253};
254
255inline phx::function<MakeCtrlModifierExpression> MakeCtrlModifier;
256
270
273
274 std::string comment;
275
277
278 std::vector<int> qubits;
279 std::vector<int> cbits;
280
281 std::vector<double> parameters;
282
283 std::vector<std::string> paramsDecl;
284 std::vector<std::string> qubitsDecl;
285
286 // Expected values are stored explicitly instead of packed into an integer,
287 // so QASM3 conjunctions are not limited by the host integer width.
288 std::vector<bool> condExpected;
289 // Condition bits for a conditional Measurement/Reset; CondUop uses cbits.
290 std::vector<int> condBits;
291 std::vector<UopType> declOps;
292};
293
295
297 boost::fusion::vector<std::vector<std::string>, double,
298 std::vector<std::string>, std::vector<StatementType>>;
299
301using MeasureType = boost::fusion::vector<ArgumentType, ArgumentType>;
303struct DelayType {
304 double duration = 0.0;
306};
307// using QopType = std::variant<UopType, ResetType, MeasureType, BarrierType>;
309using CondOpType = boost::fusion::vector<std::string, int, QopType>;
310
311// The parsed condition head of a QASM3 braced conditional, i.e. everything
312// inside `if ( ... )`. Two shapes are folded into one type rather than a
313// std::variant, matching the style of ModifierType above: each alternative
314// of the `condHead` rule (register-comparison, bare bit, negated bit) has
315// its own semantic action constructing one of these, so no
316// BOOST_FUSION_ADAPT_STRUCT/attribute propagation is needed - only direct
317// construction via qi::_val = Make...CondHead(...).
318//
319// Register form (`c == 2`): isBitForm is false, regId/regValue hold the
320// register name and comparison value - the same information CondOpType
321// carried before this type existed.
322//
323// Bit form (`c[0]`, `!c[0]`, or a `&&`-joined chain of either): isBitForm is
324// true and bits holds one entry per tested bit, each pairing the indexed
325// classical bit with the value it must equal for the condition to be true
326// (true for the bare form, false for the negated form). This is deliberately
327// expressed as bits + expected values, not a register + mask, since
328// CreateEqualCondition already takes bit indices and expected booleans
329// directly (see AddCondQopBracedExpr).
332 bool expected = true;
333};
334
336 bool isBitForm = false;
337
338 std::string regId;
339 int regValue = 0;
340
341 std::vector<CondBitTest> bits;
342};
343
345 struct result {
347 };
348
349 CondHeadType operator()(const std::string &regId, int regValue) const {
350 CondHeadType head;
351 head.isBitForm = false;
352 head.regId = regId;
353 head.regValue = regValue;
354 return head;
355 }
356};
357
358inline phx::function<MakeRegCondHeadExpression> MakeRegCondHead;
359
361 struct result {
363 };
364
365 CondBitTest operator()(const IndexedId &bit, bool expected) const {
366 CondBitTest test;
367 test.bit = bit;
368 test.expected = expected;
369 return test;
370 }
371};
372
373inline phx::function<MakeCondBitTestExpression> MakeCondBitTest;
374
376 struct result {
378 };
379
380 CondHeadType operator()(const std::vector<CondBitTest> &bits) const {
381 CondHeadType head;
382 head.isBitForm = true;
383 head.bits = bits;
384 return head;
385 }
386};
387
388inline phx::function<MakeBitCondHeadExpression> MakeBitCondHead;
389
391 boost::fusion::vector<std::string, std::vector<std::string>,
392 std::vector<std::string>>;
393using SimpleBarrierType = std::vector<std::string>;
394using GateDeclOpType = std::variant<UopType, SimpleBarrierType>;
396 boost::fusion::vector<std::string, std::vector<std::string>,
397 std::vector<std::string>>;
398
400 struct result {
402 };
403
404 IndexedId operator()(int &counter,
405 std::unordered_map<std::string, IndexedId> &creg_map,
406 DeclarationRegistry &declarations,
407 const IndexedId &id) const {
408 IndexedId id_copy = id;
409 const int size = ValidateRegisterAllocation(id_copy, counter, "Classical");
410 RegisterDeclaration(declarations, id_copy.id, DeclarationKind::Bit);
411
412 id_copy.base = counter;
413 id_copy.declType = "creg";
414
415 counter += size;
416 creg_map[id_copy.id] = id_copy;
417
418 return id_copy;
419 }
420};
421
422inline phx::function<AddCregExpr> AddCreg;
423
425 struct result {
427 };
428
429 IndexedId operator()(int &counter,
430 std::unordered_map<std::string, IndexedId> &qreg_map,
431 DeclarationRegistry &declarations,
432 const IndexedId &id) const {
433 IndexedId id_copy = id;
434 const int size = ValidateRegisterAllocation(id_copy, counter, "Quantum");
435 RegisterDeclaration(declarations, id_copy.id, DeclarationKind::Qubit);
436
437 id_copy.base = counter;
438 id_copy.declType = "qreg";
439
440 counter += size;
441 qreg_map[id_copy.id] = id_copy;
442
443 return id_copy;
444 }
445};
446
447inline phx::function<AddQregExpr> AddQreg;
448
450 struct result {
452 };
453
454 QoperationStatement operator()(const std::string &comment) const {
456
458 stmt.comment = comment;
459
460 return stmt;
461 }
462};
463
464inline phx::function<AddCommentExpr> AddComment;
465
467 struct result {
469 };
470
474 stmt.declaration = id;
475
476 return stmt;
477 }
478};
479
480inline phx::function<AddDeclarationExpr> AddDeclaration;
481
482inline void ValidateInputDeclaration(const std::string &name,
483 const std::string &type,
484 const boost::optional<int> &width) {
485 if (width && *width <= 0)
486 throw std::invalid_argument("Input '" + name +
487 "' must have a positive type width.");
488
489 if (type == "bool") {
490 if (width)
491 throw std::invalid_argument("Boolean input '" + name +
492 "' cannot have a width designator.");
493 return;
494 }
495
496 if (type == "float") {
497 if (width && *width != 32 && *width != 64)
498 throw std::invalid_argument(
499 "Input '" + name +
500 "' uses an unsupported float width; only float, float[32], and "
501 "float[64] are supported.");
502 return;
503 }
504
505 if (type == "angle") {
506 if (width)
507 throw std::invalid_argument(
508 "Precisely quantized sized angle inputs are not supported.");
509 return;
510 }
511
512 if (width && *width > 64)
513 throw std::invalid_argument("Input '" + name +
514 "' uses an integer width above 64, which "
515 "the numeric binding API cannot represent.");
516}
517
518inline double ValidateInputBinding(const std::string &name,
519 const std::string &type,
520 const boost::optional<int> &width,
521 double value) {
522 ValidateInputDeclaration(name, type, width);
523
524 if (!std::isfinite(value))
525 throw std::invalid_argument("Input binding '" + name + "' must be finite.");
526
527 if (type == "bool") {
528 if (value != 0. && value != 1.)
529 throw std::invalid_argument("Input binding '" + name +
530 "' must be a boolean value (0 or 1).");
531 return value;
532 }
533
534 if (type == "float") {
535 if (!width || *width == 64) return value;
536 const float narrowed = static_cast<float>(value);
537 if (!std::isfinite(narrowed))
538 throw std::invalid_argument("Input binding '" + name +
539 "' does not fit float[32].");
540 return static_cast<double>(narrowed);
541 }
542
543 if (type == "angle") {
544 double normalized = std::fmod(value, 2. * M_PI);
545 if (normalized < 0.) normalized += 2. * M_PI;
546 return normalized;
547 }
548
549 const bool isUnsigned = type == "uint";
550 if (std::trunc(value) != value)
551 throw std::invalid_argument("Input binding '" + name +
552 "' must be an integer value.");
553 if (isUnsigned && value < 0.)
554 throw std::invalid_argument("Unsigned input binding '" + name +
555 "' must be non-negative.");
556
557 if (width) {
558 const double upper = std::ldexp(1., isUnsigned ? *width : *width - 1);
559 const double lower = isUnsigned ? 0. : -upper;
560 if (value < lower || value >= upper)
561 throw std::invalid_argument("Input binding '" + name +
562 "' does not fit its declared " + type + "[" +
563 std::to_string(*width) + "] type.");
564 }
565
566 return value;
567}
568
569// Records a QASM3 input declaration and publishes a validated caller binding
570// to the expression environment only when that declaration is reached.
572 struct result {
574 };
575
577 const InputDeclType &inputDecl, std::vector<std::string> &inputNames,
578 DeclarationRegistry &declarations,
579 const std::unordered_map<std::string, double> &inputBindings,
580 std::unordered_map<std::string, double> &visibleInputValues) const {
581 const std::string &type = boost::fusion::at_c<0>(inputDecl);
582 const boost::optional<int> &width = boost::fusion::at_c<1>(inputDecl);
583 const std::string &name = boost::fusion::at_c<2>(inputDecl);
584 ValidateInputDeclaration(name, type, width);
585 RegisterDeclaration(declarations, name, DeclarationKind::Input);
586 inputNames.push_back(name);
587
588 const auto binding = inputBindings.find(name);
589 if (binding != inputBindings.end())
590 visibleInputValues[name] =
591 ValidateInputBinding(name, type, width, binding->second);
592
595 // Recorded in `declaration`, the same IndexedId field AddDeclarationExpr
596 // (the qreg/creg/qubit/bit declaration functor) populates, so a
597 // Declaration-typed statement always carries its declared name in one
598 // place regardless of which kind of declaration produced it. `index` is
599 // left at its default 0: an `input` has no size to record.
600 stmt.declaration = IndexedId(name, 0);
601 stmt.declaration.declType = "input";
602
603 return stmt;
604 }
605};
606
607inline phx::function<AddInputDeclExpr> AddInputDecl;
608
610 struct result {
612 };
613
615 const RegisterMap &creg_map,
616 const RegisterMap &qreg_map) const {
619
620 stmt.qubits = ResolveRegisterOperand(boost::fusion::at_c<0>(measure),
621 qreg_map, "quantum");
622 stmt.cbits = ResolveRegisterOperand(boost::fusion::at_c<1>(measure),
623 creg_map, "classical");
624 RequireMatchingRegisterWidths(stmt.qubits, stmt.cbits, "Measurement");
625
626 return stmt;
627 }
628};
629
630inline phx::function<AddMeasureExpr> AddMeasure;
631
632// The OpenQASM 3 grammar makes a measurement's `-> c` target optional, so
633// `measure q;` ("measure and throw the result away") is spec-legal. It is not
634// representable here: Circuits::CircuitFactory::CreateMeasurement takes
635// (qubit, classical bit) pairs and MeasurementOperation always writes a bit,
636// so there is no discard form to lower onto - and fabricating a classical bit
637// to absorb the result would silently grow the program's classical register
638// and change what a subsequent `if (c == ...)` sees. So the construct is
639// recognised (see `measureNoTarget` in qasm.h) and rejected by name. Before
640// this rule existed it fell through to the gate-call path and was reported as
641// "Unsupported gate without parameters: measure", which named the wrong
642// thing entirely.
644 template <typename>
645 struct result {
647 };
648
649 QoperationStatement operator()(const ArgumentType & /*qubits*/) const {
650 throw std::invalid_argument(
651 "A measurement without a classical target ('measure q;') is not "
652 "supported: every measurement must name the classical bit that "
653 "receives its result, as in 'measure q -> c;' or 'c = measure q;'");
654 }
655};
656
657inline phx::function<RejectMeasureWithoutTargetExpr> RejectMeasureWithoutTarget;
658
660 struct result {
662 };
663
665 const RegisterMap &qreg_map) const {
668 stmt.qubits = ResolveRegisterOperand(reset, qreg_map, "quantum");
669 return stmt;
670 }
671};
672
673inline phx::function<AddResetExpr> AddReset;
674
676 struct result {
678 };
679
681 const RegisterMap &qreg_map) const {
682 StatementType stmt;
684 std::set<int> qubit_set;
685
686 // A bare QASM3 barrier applies to every declared qubit. The Circuit IR
687 // has no barrier operation, so Program intentionally erases this statement.
688 if (barrier.empty()) {
689 for (const auto &[name, reg] : qreg_map)
690 for (int index = 0; index < reg.index; ++index)
691 qubit_set.insert(reg.base + index);
692 } else {
693 for (const auto &operand : barrier) {
694 const std::vector<int> resolved =
695 ResolveRegisterOperand(operand, qreg_map, "quantum");
696 qubit_set.insert(resolved.begin(), resolved.end());
697 }
698 }
699
700 stmt.qubits.assign(qubit_set.begin(), qubit_set.end());
701 return stmt;
702 }
703};
704
705inline phx::function<AddBarrierExpr> AddBarrier;
706
708 template <typename, typename, typename>
709 struct result {
711 };
712
713 template <typename D, typename M, typename V>
714 DelayType operator()(const D &dur, const M &operands,
715 const V &variables) const {
716 const auto &expr = boost::fusion::at_c<0>(dur);
717 const auto &unitOpt = boost::fusion::at_c<1>(dur);
718 double val = expr.Eval(variables);
719 double scale = unitOpt ? *unitOpt : 1.0;
720 if (scale < 0.0) {
721 throw std::invalid_argument(
722 "OpenQASM 'dt' unit delays require hardware timing context and are not "
723 "supported without a target waveform configuration.");
724 }
725 return DelayType{val * scale, operands};
726 }
727};
728
729inline phx::function<MakeDelayExpr> MakeDelay;
730
732 struct result {
734 };
735
737 const RegisterMap &qreg_map) const {
740 stmt.parameters = {delay.duration};
741 for (const auto &operand : delay.operands) {
742 const std::vector<int> resolved =
743 ResolveRegisterOperand(operand, qreg_map, "quantum");
744 stmt.qubits.insert(stmt.qubits.end(), resolved.begin(), resolved.end());
745 }
746 return stmt;
747 }
748};
749
750inline phx::function<AddDelayExpr> AddDelay;
751
753 struct result {
755 };
756
758 const OpaqueDeclType &opaqueDecl,
759 std::unordered_map<std::string, StatementType> &opaqueGates,
760 const std::unordered_map<std::string, IndexedId> &qreg_map,
761 DeclarationRegistry &declarations) const {
762 StatementType stmt;
764
765 std::string gateName = boost::fusion::at_c<0>(opaqueDecl);
766 RegisterDeclaration(declarations, gateName, DeclarationKind::Opaque);
767
768 stmt.comment = gateName;
769
770 // maybe take some other infor from opaqueDecl if needed
771 const std::vector<std::string> &params = boost::fusion::at_c<1>(opaqueDecl);
772 const std::vector<std::string> &args = boost::fusion::at_c<2>(opaqueDecl);
773
774 stmt.paramsDecl = params;
775 stmt.qubitsDecl = args;
776
777 // save into the map as well
778 opaqueGates[gateName] = stmt;
779
780 return stmt;
781 }
782};
783
784inline phx::function<AddOpaqueDeclExpr> AddOpaqueDecl;
785
787 struct result {
789 };
790
792 const boost::fusion::vector<GateDeclType, std::vector<GateDeclOpType>>
793 &gateDecl,
794 std::unordered_map<std::string, StatementType> &definedGates,
795 DeclarationRegistry &declarations) const {
796 StatementType stmt;
798
799 const GateDeclType &declInfo = boost::fusion::at_c<0>(gateDecl);
800
801 const std::string &gateName = boost::fusion::at_c<0>(declInfo);
802 const std::vector<std::string> &params = boost::fusion::at_c<1>(declInfo);
803 const std::vector<std::string> &args = boost::fusion::at_c<2>(declInfo);
804
805 RegisterDeclaration(declarations, gateName, DeclarationKind::Gate);
806
807 if (args.empty())
808 throw std::invalid_argument(
809 "Gate declaration must have at least one qubit argument: " +
810 gateName);
811 else if (definedGates.find(gateName) !=
812 definedGates
813 .end()) // for now do not allow redefinition, the
814 // biggest problem is that defined gates can be
815 // used inside other defined gates, otherwise
816 // redefinition would be simple to handle
817 throw std::invalid_argument("Gate already defined: " + gateName);
818
819 stmt.comment = gateName;
820 stmt.paramsDecl = params;
821 stmt.qubitsDecl = args;
822
823 const std::vector<GateDeclOpType> &declOps =
824 boost::fusion::at_c<1>(gateDecl);
825
826 for (const auto &op : declOps) {
827 if (std::holds_alternative<UopType>(op)) {
828 const UopType &uop = std::get<UopType>(op);
829
830 stmt.declOps.push_back(uop);
831 }
832 // ignore barriers
833 // else if (std::holds_alternative<SimpleBarrierType>(op))
834 //{
835 //}
836 }
837
838 definedGates[gateName] = stmt;
839
840 return stmt;
841 }
842};
843
844inline phx::function<AddGateDeclExpr> AddGateDecl;
845} // namespace qasm
846
847#endif
double Eval() const
Definition SimpleOps.h:34
IndexedId(const std::string &id, int index)
Definition SimpleOps.h:30
std::string id
Definition SimpleOps.h:40
std::string declType
Definition SimpleOps.h:43
QuantumGateType
The type of quantum gates.
phx::function< MakeRegCondHeadExpression > MakeRegCondHead
Definition SimpleOps.h:358
std::variant< UGateCallType, CXGateCallType, GatecallType > UopType
Definition SimpleOps.h:167
double ValidateInputBinding(const std::string &name, const std::string &type, const boost::optional< int > &width, double value)
Definition SimpleOps.h:518
boost::fusion::vector< std::string, MixedListType > SimpleGatecallType
Definition SimpleOps.h:158
std::variant< double, int, std::string > SimpleExpType
Definition SimpleOps.h:109
MixedListType BarrierType
Definition SimpleOps.h:302
std::unordered_map< std::string, DeclarationKind > DeclarationRegistry
Definition SimpleOps.h:48
StatementType QopType
Definition SimpleOps.h:308
boost::fusion::vector< std::string, std::vector< std::string >, std::vector< std::string > > GateDeclType
Definition SimpleOps.h:390
phx::function< MakeCondBitTestExpression > MakeCondBitTest
Definition SimpleOps.h:373
std::vector< ArgumentType > MixedListType
Definition SimpleOps.h:113
phx::function< MakeCtrlModifierExpression > MakeCtrlModifier
Definition SimpleOps.h:255
std::vector< ModifierType > ModifierListType
Definition SimpleOps.h:192
std::variant< SimpleGatecallType, ExpGatecallType > GatecallType
Definition SimpleOps.h:161
phx::function< RejectMeasureWithoutTargetExpr > RejectMeasureWithoutTarget
Definition SimpleOps.h:657
DeclarationKind
Definition SimpleOps.h:46
phx::function< AddQregExpr > AddQreg
Definition SimpleOps.h:447
boost::fusion::vector< ArgumentType, ArgumentType > CXGateCallType
Definition SimpleOps.h:165
ModifierKind
Definition SimpleOps.h:171
phx::function< MakeIndexedIdExpression > MakeIndexedId
Definition SimpleOps.h:107
phx::function< AddCommentExpr > AddComment
Definition SimpleOps.h:464
boost::fusion::vector< std::vector< std::string >, double, std::vector< std::string >, std::vector< StatementType > > ProgramType
Definition SimpleOps.h:296
void RequireMatchingRegisterWidths(const std::vector< int > &left, const std::vector< int > &right, std::string_view operation)
Definition SimpleOps.h:150
phx::function< AddDeclarationExpr > AddDeclaration
Definition SimpleOps.h:480
phx::function< MakeDelayExpr > MakeDelay
Definition SimpleOps.h:729
phx::function< AddBarrierExpr > AddBarrier
Definition SimpleOps.h:705
std::string regId
Definition SimpleOps.h:338
std::vector< std::string > SimpleBarrierType
Definition SimpleOps.h:393
phx::function< AddCregExpr > AddCreg
Definition SimpleOps.h:422
std::vector< CondBitTest > bits
Definition SimpleOps.h:341
boost::fusion::vector< std::string, std::vector< Expression >, MixedListType > ExpGatecallType
Definition SimpleOps.h:159
boost::fusion::vector< std::string, int, QopType > CondOpType
Definition SimpleOps.h:309
void ValidateInputDeclaration(const std::string &name, const std::string &type, const boost::optional< int > &width)
Definition SimpleOps.h:482
boost::fusion::vector< std::vector< Expression >, ArgumentType > UGateCallType
Definition SimpleOps.h:163
phx::function< MakePowModifierExpression > MakePowModifier
Definition SimpleOps.h:214
boost::fusion::vector< ModifierListType, UopType > ModifiedUopType
Definition SimpleOps.h:193
phx::function< AddOpaqueDeclExpr > AddOpaqueDecl
Definition SimpleOps.h:784
phx::function< MakeBitCondHeadExpression > MakeBitCondHead
Definition SimpleOps.h:388
std::variant< std::string, IndexedId > ArgumentType
Definition SimpleOps.h:111
boost::fusion::vector< std::string, std::vector< std::string >, std::vector< std::string > > OpaqueDeclType
Definition SimpleOps.h:395
phx::function< AddDelayExpr > AddDelay
Definition SimpleOps.h:750
QoperationStatement StatementType
Definition SimpleOps.h:294
phx::function< AddMeasureExpr > AddMeasure
Definition SimpleOps.h:630
MixedListType operands
Definition SimpleOps.h:305
phx::function< AddInputDeclExpr > AddInputDecl
Definition SimpleOps.h:607
int ValidateRegisterAllocation(const IndexedId &id, int currentSize, std::string_view kind)
Definition SimpleOps.h:80
phx::function< AddGateDeclExpr > AddGateDecl
Definition SimpleOps.h:844
std::variant< UopType, SimpleBarrierType > GateDeclOpType
Definition SimpleOps.h:394
ArgumentType ResetType
Definition SimpleOps.h:300
std::vector< int > ResolveRegisterOperand(const ArgumentType &argument, const RegisterMap &registers, std::string_view kind)
Definition SimpleOps.h:117
boost::fusion::vector< ArgumentType, ArgumentType > MeasureType
Definition SimpleOps.h:301
boost::fusion::vector< std::string, boost::optional< int >, std::string > InputDeclType
Definition SimpleOps.h:114
std::unordered_map< std::string, IndexedId > RegisterMap
Definition SimpleOps.h:112
std::string_view DeclarationKindName(DeclarationKind kind)
Definition SimpleOps.h:50
void RegisterDeclaration(DeclarationRegistry &declarations, const std::string &name, DeclarationKind kind)
Definition SimpleOps.h:67
phx::function< AddResetExpr > AddReset
Definition SimpleOps.h:673
QoperationStatement operator()(const BarrierType &barrier, const RegisterMap &qreg_map) const
Definition SimpleOps.h:680
QoperationStatement type
Definition SimpleOps.h:677
QoperationStatement operator()(const std::string &comment) const
Definition SimpleOps.h:454
QoperationStatement type
Definition SimpleOps.h:451
IndexedId operator()(int &counter, std::unordered_map< std::string, IndexedId > &creg_map, DeclarationRegistry &declarations, const IndexedId &id) const
Definition SimpleOps.h:404
QoperationStatement operator()(const IndexedId &id) const
Definition SimpleOps.h:471
QoperationStatement type
Definition SimpleOps.h:733
QoperationStatement operator()(const DelayType &delay, const RegisterMap &qreg_map) const
Definition SimpleOps.h:736
QoperationStatement type
Definition SimpleOps.h:788
QoperationStatement operator()(const boost::fusion::vector< GateDeclType, std::vector< GateDeclOpType > > &gateDecl, std::unordered_map< std::string, StatementType > &definedGates, DeclarationRegistry &declarations) const
Definition SimpleOps.h:791
QoperationStatement type
Definition SimpleOps.h:573
QoperationStatement operator()(const InputDeclType &inputDecl, std::vector< std::string > &inputNames, DeclarationRegistry &declarations, const std::unordered_map< std::string, double > &inputBindings, std::unordered_map< std::string, double > &visibleInputValues) const
Definition SimpleOps.h:576
QoperationStatement type
Definition SimpleOps.h:611
QoperationStatement operator()(const MeasureType &measure, const RegisterMap &creg_map, const RegisterMap &qreg_map) const
Definition SimpleOps.h:614
QoperationStatement type
Definition SimpleOps.h:754
QoperationStatement operator()(const OpaqueDeclType &opaqueDecl, std::unordered_map< std::string, StatementType > &opaqueGates, const std::unordered_map< std::string, IndexedId > &qreg_map, DeclarationRegistry &declarations) const
Definition SimpleOps.h:757
IndexedId operator()(int &counter, std::unordered_map< std::string, IndexedId > &qreg_map, DeclarationRegistry &declarations, const IndexedId &id) const
Definition SimpleOps.h:429
QoperationStatement type
Definition SimpleOps.h:661
QoperationStatement operator()(const ResetType &reset, const RegisterMap &qreg_map) const
Definition SimpleOps.h:664
CondHeadType operator()(const std::vector< CondBitTest > &bits) const
Definition SimpleOps.h:380
CondBitTest operator()(const IndexedId &bit, bool expected) const
Definition SimpleOps.h:365
ModifierType operator()(K kind, const E &count, const V &variables) const
Definition SimpleOps.h:233
DelayType operator()(const D &dur, const M &operands, const V &variables) const
Definition SimpleOps.h:714
IndexedId operator()(const ID &id, IND index) const
Definition SimpleOps.h:102
ModifierType operator()(const E &exponent, const V &variables) const
Definition SimpleOps.h:209
CondHeadType operator()(const std::string &regId, int regValue) const
Definition SimpleOps.h:349
ModifierKind kind
Definition SimpleOps.h:178
ModifierType()=default
ModifierType(ModifierKind kind, double exponent=0., int count=1)
Definition SimpleOps.h:175
std::vector< UopType > declOps
Definition SimpleOps.h:291
std::vector< bool > condExpected
Definition SimpleOps.h:288
std::vector< int > condBits
Definition SimpleOps.h:290
std::vector< std::string > qubitsDecl
Definition SimpleOps.h:284
std::vector< double > parameters
Definition SimpleOps.h:281
std::vector< int > cbits
Definition SimpleOps.h:279
std::vector< std::string > paramsDecl
Definition SimpleOps.h:283
std::vector< int > qubits
Definition SimpleOps.h:278
Circuits::QuantumGateType gateType
Definition SimpleOps.h:272
QoperationStatement operator()(const ArgumentType &) const
Definition SimpleOps.h:649