Source code for mimiqcircuits.operations.ifstatement

#
# Copyright © 2022-2023 University of Strasbourg. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from mimiqcircuits.operations.operation import Operation
import symengine as se
import sympy as sp
import mimiqcircuits as mc
from mimiqcircuits.canvas import _find_unit_range, _string_with_square


[docs] class IfStatement(Operation): """Conditional operation This operation applies a specific operation if a given classical bit condition is met. Examples: >>> from mimiqcircuits import * >>> c = Circuit() >>> c.push(IfStatement(GateX(), 1,1), 0,0) init if -> operation= X 1-qubit circuit with 1 instructions: └── IF(c == 1) X @ q[0], c[0] <BLANKLINE> """ _name = "If" _num_qubits = None _num_bits = None _num_cregs = 1 _op = None _val = None def __init__(self, operation, num_bits, val, *args, **kwargs): print("init if -> operation=", operation) if isinstance(operation, type) and issubclass(operation, Operation): op = operation(*args, **kwargs) elif isinstance(operation, Operation): op = operation else: raise ValueError("Operation must be an Operation object or type.") if not isinstance(val, int) or val < 0: raise ValueError("val must be a positive integer") super().__init__() self._num_qubits = op.num_qubits self._num_qregs = op.num_qregs self._qregsizes = op.qregsizes self._num_bits = num_bits self._num_cregs = 1 self._cregsizes = [ num_bits, ] self._op = op self._val = val @property def op(self): return self._op @op.setter def op(self, op): raise ValueError("Cannot set op. Read only parameter.") @property def val(self): return self._val @val.setter def val(self, val): raise ValueError("Cannot set val. Read only parameter.")
[docs] def iswrapper(self): return True
[docs] def getparams(self): return self.op.getparams()
[docs] def inverse(self): raise NotImplementedError("Inverse not implemented for IfStatement")
[docs] def power(self, power): raise NotImplementedError("Power not implemented for IfStatement")
[docs] def control(self, num_controls): raise NotImplementedError("Control not implemented for IfStatement")
def __str__(self): return f"IF(c == {self.val}) {self.op}"
[docs] def evaluate(self, d): return IfStatement(self.op.evaluate(d), self.num_bits, self.val)
[docs] def get_unwrapped_value(self): v = sp.simplify(self.val) if isinstance(v, sp.Number): return float(v) elif isinstance(v, sp.pi): return sp.pi.evalf() elif isinstance(v, sp.E): return sp.E.evalf()
[docs] def get_operation(self): return self.op
[docs] def asciiwidth(self, qubits, bits): val = self.get_unwrapped_value() gw = self.op.asciiwidth(qubits, []) bstr = _string_with_square(_find_unit_range(bits), ",") iw = len(f"c{bstr} == 0x{val}") + 3 # :x formats val as hex return max(gw, iw)
def _decompose(self, circuit, qtargets, ctargets): decomposed_insts = self.op.decompose() for inst in decomposed_insts: conditional_operation = IfStatement(inst.operation, self._num_bits, self._val) targeted_qubits = [qtargets[i] for i in inst.get_qubits()] circuit.push(conditional_operation, *targeted_qubits, *ctargets) return circuit
__all__ = ["IfStatement"]