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