diff --git a/qlasskit/qcircuit/gates.py b/qlasskit/qcircuit/gates.py index a9e4b0dd..36303715 100644 --- a/qlasskit/qcircuit/gates.py +++ b/qlasskit/qcircuit/gates.py @@ -83,11 +83,11 @@ def __init__(self, gate, n_controls): def apply(gate: QGate, qubits: List[int], param=None): if len(qubits) != gate.n_qubits: raise Exception(f"expected {gate.n_qubits} qubits ({len(qubits)} given)") - return [gate, qubits, param] + return ( + gate, + qubits, + param, + ) AppliedGate = Tuple[QGate, List[int], Any] - -# qc.append(CX(), [0, 1]) -# qc += apply(CX(), [0, 1]) -# qc += another_circ diff --git a/qlasskit/qcircuit/qcircuit.py b/qlasskit/qcircuit/qcircuit.py index 0d70d240..187a47e6 100644 --- a/qlasskit/qcircuit/qcircuit.py +++ b/qlasskit/qcircuit/qcircuit.py @@ -6,12 +6,14 @@ # http://www.apache.org/licenses/LICENSE-2.0 +import copy + # 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 typing import Any, List, Literal, Union +from typing import Any, List, Literal, Tuple, Union from sympy import Symbol @@ -78,7 +80,28 @@ def __getitem__(self, key: Union[str, Symbol, int]): def __add__(self, qc: "QCircuit") -> "QCircuit": """Create a new QCircuit that merges two""" - raise Exception("not implemented") + nqc = copy.deepcopy(self) + nqc += qc + return nqc + + def __iadd__(self, other: Union[gates.AppliedGate, "QCircuit"]): # type: ignore + """AugAssign between a qcircuit and a AppliedGate|QCircuit""" + if isinstance(other, Tuple): # type: ignore + self.append(other[0], other[1], other[2]) + elif isinstance(other, QCircuit): # type: ignore + if other.num_qubits > self.num_qubits: + raise Exception( + f"Other circuit has too many qubits {other.num_qubits} > {self.num_qubits}" + ) + + self.gates.extend(other.gates) + self.gates_computed.extend(other.gates_computed) + + for s, q in other.qubit_map.items(): + if s not in self.qubit_map: + self.qubit_map[s] = q + + return self def add_qubit(self, name=None): """Add a qubit to the circuit. diff --git a/qlasskit/utils.py b/qlasskit/utils.py deleted file mode 100644 index dd9ee251..00000000 --- a/qlasskit/utils.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2023 Davide Gessa - -# 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 sympy.logic.boolalg import And, BooleanFunction, Xor - - -class BToffoli(BooleanFunction): - """ - Logical Toffoli function; invert the third argument, if the first two are True. - - c XOR (a AND b) - - Examples - ======== - - >>> BToffoli(False, False, True) - True - >>> BToffoli(True, True, True) - False - >>> BToffoli(True, True, False) - True - - """ - - @classmethod - def eval(cls, a, b, c): - return Xor(c, And(a, b)) diff --git a/test/test_qcircuit.py b/test/test_qcircuit.py index 31bffb07..5b152edd 100644 --- a/test/test_qcircuit.py +++ b/test/test_qcircuit.py @@ -36,7 +36,7 @@ def test_base_mapping(self): qc.ccx("a", Symbol("b"), c) self.assertEqual(qc.num_qubits, 3) self.assertTrue(isinstance(qc.gates[0][0], gates.CCX)) - self.assertEqual(qc.gates[0][1:], [[0, 1, 2], None]) + self.assertEqual(qc.gates[0][1:], ([0, 1, 2], None)) def test_duplicate_qubit(self): qc = QCircuit() @@ -47,6 +47,17 @@ def test_mapping(self): qc = QCircuit(4) qc.ccx("q0", "q1", "q2") + def test_augassign(self): + qc = QCircuit(1) + qc += gates.apply(gates.X(), [0]) + + def test_augassign_othercirc(self): + qc = QCircuit(1) + qc += gates.apply(gates.X(), [0]) + + qc2 = QCircuit(1) + qc2 += qc + def test_get_key_by_index(self): qc = QCircuit() a, b = qc.add_qubit("a"), qc.add_qubit("b")