コード例 #1
0
def test_str():
    c1 = cirq.NamedQubit('c1')
    c2 = cirq.NamedQubit('c2')
    q2 = cirq.NamedQubit('q2')

    assert (str(cirq.ControlledOperation([c1],
                                         cirq.CZ(c2,
                                                 q2))) == "CCZ(c1, c2, q2)")

    class SingleQubitOp(cirq.Operation):
        def qubits(self) -> Tuple[cirq.Qid, ...]:
            pass

        def with_qubits(self, *new_qubits: cirq.Qid):
            pass

        def __str__(self):
            return "Op(q2)"

    assert (str(cirq.ControlledOperation(
        [c1, c2], SingleQubitOp())) == "C(c1, c2, Op(q2))")
コード例 #2
0
def test_controlled_operation_init():
    cb = cirq.NamedQubit('ctr')
    q = cirq.NamedQubit('q')
    g = cirq.SingleQubitGate()
    v = cirq.GateOperation(g, (q,))
    c = cirq.ControlledOperation([cb], v)
    assert c.sub_operation == v
    assert c.controls == (cb,)
    assert c.qubits == (cb, q)
    assert c == c.with_qubits(cb, q)
    assert c.control_values == ((1,),)
    assert cirq.qid_shape(c) == (2, 2)

    c = cirq.ControlledOperation([cb], v, control_values=[0])
    assert c.sub_operation == v
    assert c.controls == (cb,)
    assert c.qubits == (cb, q)
    assert c == c.with_qubits(cb, q)
    assert c.control_values == ((0,),)
    assert cirq.qid_shape(c) == (2, 2)

    c = cirq.ControlledOperation([cb.with_dimension(3)], v)
    assert c.sub_operation == v
    assert c.controls == (cb.with_dimension(3),)
    assert c.qubits == (cb.with_dimension(3), q)
    assert c == c.with_qubits(cb.with_dimension(3), q)
    assert c.control_values == ((1,),)
    assert cirq.qid_shape(c) == (3, 2)

    with pytest.raises(ValueError, match=r'len\(control_values\) != len\(controls\)'):
        _ = cirq.ControlledOperation([cb], v, control_values=[1, 1])
    with pytest.raises(ValueError, match='Control values .*outside of range'):
        _ = cirq.ControlledOperation([cb], v, control_values=[2])
    with pytest.raises(ValueError, match='Control values .*outside of range'):
        _ = cirq.ControlledOperation([cb], v, control_values=[(1, -1)])
コード例 #3
0
def test_uninformed_circuit_diagram_info():
    qbits = cirq.LineQubit.range(3)
    mock_gate = MockGate()
    c_op = cirq.ControlledOperation(qbits[:1], mock_gate(*qbits[1:]))

    args = protocols.CircuitDiagramInfoArgs.UNINFORMED_DEFAULT

    assert cirq.circuit_diagram_info(c_op, args) == cirq.CircuitDiagramInfo(
        wire_symbols=('@', 'M1', 'M2'),
        exponent=1,
        connected=True,
        exponent_qubit_index=1)
    assert mock_gate.captured_diagram_args == args
コード例 #4
0
ファイル: control_test.py プロジェクト: fieldplay/Cirq
def test_op_tree_control():
    gs = [cirq.SingleQubitGate() for _ in range(10)]
    op_tree = [
        cirq.GateOperation(gs[i], [cirq.NamedQubit(str(i))]) for i in range(10)
    ]
    controls = cirq.LineQubit.range(2)
    controlled_op_tree = cirq.protocols.control(op_tree, controls)
    expected = [
        cirq.ControlledOperation(
            controls, cirq.GateOperation(gs[i], [cirq.NamedQubit(str(i))]))
        for i in range(10)
    ]
    assert cirq.freeze_op_tree(controlled_op_tree) == tuple(expected)
コード例 #5
0
def test_circuit_diagram():
    qubits = cirq.LineQubit.range(3)
    c = cirq.Circuit()
    c.append(cirq.ControlledOperation(qubits[0], MultiH(2)(*qubits[1:])))

    cirq.testing.assert_has_diagram(
        c, """
0: ───@──────
      │
1: ───H(1)───
      │
2: ───H(2)───
""")
コード例 #6
0
def test_str():
    c1 = cirq.NamedQubit('c1')
    c2 = cirq.NamedQubit('c2')
    q2 = cirq.NamedQubit('q2')

    assert str(cirq.ControlledOperation([c1], cirq.CZ(c2, q2))) == "CCZ(c1, c2, q2)"

    class SingleQubitOp(cirq.Operation):
        @property
        def qubits(self) -> Tuple[cirq.Qid, ...]:
            return ()

        def with_qubits(self, *new_qubits: cirq.Qid):
            pass

        def __str__(self):
            return "Op(q2)"

        def _has_mixture_(self):
            return True

    assert str(cirq.ControlledOperation([c1, c2], SingleQubitOp())) == "CC(c1, c2, Op(q2))"

    assert (
        str(cirq.ControlledOperation([c1, c2.with_dimension(3)], SingleQubitOp()))
        == "CC(c1, c2 (d=3), Op(q2))"
    )

    assert (
        str(
            cirq.ControlledOperation(
                [c1, c2.with_dimension(3)], SingleQubitOp(), control_values=[1, (2, 0)]
            )
        )
        == "C1C02(c1, c2 (d=3), Op(q2))"
    )
コード例 #7
0
    def cnot_to_controlled_parallel_x(self, circuit, index, operation):
        p_op = cirq.ParallelGateOperation(cirq.ops.X, [operation.qubits[1]])
        current_controlled_op = \
            cirq.ControlledOperation([operation.qubits[0]], p_op)

        # print("A--------> ", len(circuit))
        circuit.clear_operations_touching(operation.qubits, [index])
        # print("B--------> ", len(circuit), repr(circuit))

        # Is this an issue about how operations are inserted?
        circuit.insert(index + 1,
                       current_controlled_op,
                       strategy=cirq.InsertStrategy.INLINE)
        # print("C--------> ", len(circuit), repr(circuit))

        return current_controlled_op
コード例 #8
0
def test_controlled_operation_eq():
    c1 = cirq.NamedQubit('c1')
    q1 = cirq.NamedQubit('q1')
    c2 = cirq.NamedQubit('c2')

    eq = cirq.testing.EqualsTester()

    eq.make_equality_group(lambda: cirq.ControlledOperation([c1], cirq.X(q1)))
    eq.make_equality_group(lambda: cirq.ControlledOperation([c2], cirq.X(q1)))
    eq.make_equality_group(lambda: cirq.ControlledOperation([c1], cirq.Z(q1)))
    eq.add_equality_group(cirq.ControlledOperation([c2], cirq.Z(q1)))
    eq.add_equality_group(cirq.ControlledOperation([c1, c2], cirq.Z(q1)),
                          cirq.ControlledOperation([c2, c1], cirq.Z(q1)))
コード例 #9
0
def test_controlled_operation_eq():
    c1 = cirq.NamedQubit('c1')
    q1 = cirq.NamedQubit('q1')
    c2 = cirq.NamedQubit('c2')

    eq = cirq.testing.EqualsTester()

    eq.make_equality_group(lambda: cirq.ControlledOperation([c1], cirq.X(q1)))
    eq.make_equality_group(lambda: cirq.ControlledOperation([c2], cirq.X(q1)))
    eq.make_equality_group(lambda: cirq.ControlledOperation([c1], cirq.Z(q1)))
    eq.add_equality_group(cirq.ControlledOperation([c2], cirq.Z(q1)))
    eq.add_equality_group(cirq.ControlledOperation([c1, c2], cirq.Z(q1)),
                          cirq.ControlledOperation([c2, c1], cirq.Z(q1)))
    eq.add_equality_group(
        cirq.ControlledOperation([c1, c2.with_dimension(3)],
                                 cirq.Z(q1),
                                 control_values=[1, (0, 2)]),
        cirq.ControlledOperation([c2.with_dimension(3), c1],
                                 cirq.Z(q1),
                                 control_values=[(2, 0), 1]))
コード例 #10
0
    def merge_controlled_parallel_x(self, op1, op2):

        if (len(op1.controls) != len(op2.controls)) \
            and (len(op1.controls) != 1) \
            and op1.controls[0] != op2.controls[0]:
            return

        merged_qubits = op1.sub_operation.qubits + \
                    op2.sub_operation.qubits

        try:
            p_op = cirq.ParallelGateOperation(cirq.ops.X, merged_qubits)
        except ValueError as e:
            print(e, merged_qubits)

        merged_op = cirq.ControlledOperation([op1.controls[0]],
                                             sub_operation=p_op)

        return merged_op
コード例 #11
0
def make_grover_circuit(n: int, input_qubit, f):
    """Find the value recognized by the oracle in sqrt(N) attempts."""
    # For 2 input qubits, that means using Grover operator only once.
    c = cirq.Circuit()  # circuit begin

    c.append(cirq.H.on(input_qubit[0]))  # number=1
    c.append(cirq.H.on(input_qubit[1]))  # number=4
    c.append(cirq.H.on(input_qubit[1]))  # number=21
    c.append(cirq.H.on(input_qubit[2]))  # number=5
    c.append(cirq.CZ.on(input_qubit[3], input_qubits[1]))  # number=6

    repeat = floor(sqrt(2**n) * pi / 4)
    for i in range(repeat):
        c.append(make_oracle(input_qubit, n, f))
        c.append(cirq.H.on(input_qubit[0]))  # number=3
        c.append(cirq.H.on(input_qubit[1]))  # number=2
        c.append(cirq.H.on(input_qubit[2]))  # number=7
        c.append(cirq.H.on(input_qubit[3]))  # number=8

        c.append(cirq.X.on(input_qubit[0]))  # number=9
        c.append(cirq.X.on(input_qubit[1]))  # number=10
        c.append(cirq.X.on(input_qubit[2]))  # number=11
        c.append(cirq.X.on(input_qubit[3]))  # number=12

        c.append(
            cirq.ControlledOperation(input_qubit[1:],
                                     cirq.Z.on(input_qubit[0])))

        c.append(cirq.X.on(input_qubit[0]))  # number=13
        c.append(cirq.X.on(input_qubit[1]))  # number=14
        c.append(cirq.X.on(input_qubit[2]))  # number=15
        c.append(cirq.X.on(input_qubit[3]))  # number=16

        c.append(cirq.H.on(input_qubit[0]))  # number=17
        c.append(cirq.H.on(input_qubit[1]))  # number=18
        c.append(cirq.H.on(input_qubit[2]))  # number=19
        c.append(cirq.H.on(input_qubit[3]))  # number=20

    # circuit end

    c.append(cirq.measure(*input_qubit, key='result'))

    return c
コード例 #12
0
def make_oracle(input_qubits, n: int, f):
    """Implement function {f(x) = 1 if x==x', f(x) = 0 if x!= x'}."""
    # Make oracle.
    # for (1, 1) it's just a Toffoli gate
    # otherwise negate the zero-bits.
    #yield(cirq.X(q) for (q, bit) in zip(input_qubits, x_bits) if not bit)
    #yield(cirq.TOFFOLI(input_qubits[0], input_qubits[1], output_qubit))
    #yield(cirq.X(q) for (q, bit) in zip(input_qubits, x_bits) if not bit)

    for i in range(2**n):
        rep = np.binary_repr(i, n)
        if f(rep) == "1":
            for j in range(n):
                if rep[j] == "0":
                    yield (cirq.X(input_qubits[j]))

            yield (cirq.ControlledOperation(input_qubits[1:],
                                            cirq.Z.on(input_qubits[0])))

            for j in range(n):
                if rep[j] == "0":
                    yield (cirq.X(input_qubits[j]))
コード例 #13
0
ファイル: control_test.py プロジェクト: fieldplay/Cirq
    assert cirq.protocols.control(controllee, [p],
                                  NotImplemented) is NotImplemented
    assert cirq.protocols.control(controllee, [p], None) is None
    assert cirq.protocols.control(controllee, [p, q], None) is None


def test_controlled_by_error():
    with pytest.raises(TypeError, match="returned NotImplemented"):
        _ = cirq.protocols.control(ReturnsNotImplemented(), [p])
    with pytest.raises(TypeError, match="no controlled_by method"):
        _ = cirq.protocols.control(NoMethod(), [p])


@pytest.mark.parametrize(
    'controllee,control_qubits,out',
    ((dummy_op, [q], cirq.ControlledOperation([q], dummy_op)), ))
def test_pow_with_result(controllee, control_qubits, out):
    assert (cirq.protocols.control(controllee, control_qubits) ==
            cirq.protocols.control(controllee, control_qubits,
                                   default=None) == out)


def test_op_tree_control():
    gs = [cirq.SingleQubitGate() for _ in range(10)]
    op_tree = [
        cirq.GateOperation(gs[i], [cirq.NamedQubit(str(i))]) for i in range(10)
    ]
    controls = cirq.LineQubit.range(2)
    controlled_op_tree = cirq.protocols.control(op_tree, controls)
    expected = [
        cirq.ControlledOperation(
コード例 #14
0
ファイル: stabilizer_code.py プロジェクト: towynlin/Cirq
    def correct(self, qubits: List[cirq.Qid],
                ancillas: List[cirq.Qid]) -> cirq.Circuit:
        """Corrects the code word.

        Creates a correction circuit by computing the syndrome on the ancillas, and then using this
        syndrome to correct the qubits.

        Args:
            qubits: a vector of self.n qubits that contains (potentially corrupted) code words
            ancillas: a vector of self.n - self.k qubits that are set to zero and will contain the
                syndrome once the circuit is applied.

        Returns:
            The circuit that both computes the syndrome and uses this syndrome to correct errors.
        """
        circuit = cirq.Circuit()

        gate_dict = {'X': cirq.X, 'Y': cirq.Y, 'Z': cirq.Z}

        # We set the ancillas so that measuring them directly would be the same
        # as measuring the qubits with Pauli strings. In other words, we store
        # the syndrome inside the ancillas.
        for r in range(self.n - self.k):
            for n in range(self.n):
                if self.M[r][n] == 'Z':
                    circuit.append(
                        cirq.ControlledOperation([qubits[n]],
                                                 cirq.X(ancillas[r])))
                elif self.M[r][n] == 'X':
                    circuit.append(cirq.H(qubits[n]))
                    circuit.append(
                        cirq.ControlledOperation([qubits[n]],
                                                 cirq.X(ancillas[r])))
                    circuit.append(cirq.H(qubits[n]))
                elif self.M[r][n] == 'Y':
                    circuit.append(cirq.S(qubits[n])**-1)
                    circuit.append(cirq.H(qubits[n]))
                    circuit.append(
                        cirq.ControlledOperation([qubits[n]],
                                                 cirq.X(ancillas[r])))
                    circuit.append(cirq.H(qubits[n]))
                    circuit.append(cirq.S(qubits[n]))

        # At this stage, the ancillas are equal to the syndrome. Now, we apply
        # the errors back to correct the code.

        for syndrome, correction in self.syndromes_to_corrections.items():
            op = gate_dict[correction[0]]
            n = correction[1]

            # We do a Boolean operation on the ancillas (i.e. syndrome).
            for r in range(self.n - self.k):
                if syndrome[r] == 1:
                    circuit.append(cirq.X(ancillas[r]))

            circuit.append(cirq.ControlledOperation(ancillas, op(qubits[n])))

            for r in range(self.n - self.k):
                if syndrome[r] == 1:
                    circuit.append(cirq.X(ancillas[r]))

        return circuit
コード例 #15
0
ファイル: stabilizer_code.py プロジェクト: towynlin/Cirq
    def encode(self, additional_qubits: List[cirq.Qid],
               unencoded_qubits: List[cirq.Qid]) -> cirq.Circuit:
        """Creates a circuit that encodes the qubits using the code words.

        Args:
            additional_qubits: The list of self.n - self.k qubits needed to encode the qubit.
            unencoded_qubits: The list of self.k qubits that contain the original message.

        Returns:
            A circuit where the self.n qubits are the encoded qubits.
        """
        assert len(additional_qubits) == self.n - self.k
        assert len(unencoded_qubits) == self.k
        qubits = additional_qubits + unencoded_qubits

        circuit = cirq.Circuit()

        # Equation 4.8:
        # This follows the improvements of:
        # https://cs269q.stanford.edu/projects2019/stabilizer_code_report_Y.pdf
        for r, x in enumerate(self.logical_Xs):
            for j in range(self.r, self.n - self.k):
                # By constructions, the first r rows can never contain a Z, as
                # r is defined by the Gaussian elimination as the rank.
                if x[j] == 'X' or x[j] == 'Y':
                    circuit.append(
                        cirq.ControlledOperation([unencoded_qubits[r]],
                                                 cirq.X(additional_qubits[j])))

        gate_dict = {'X': cirq.X, 'Y': cirq.Y, 'Z': cirq.Z}

        for r in range(self.r):
            circuit.append(cirq.H(qubits[r]))

            # Let's consider the first stabilizer:
            # The reason for adding S gate is Y gate we used is the complex format (i.e. to
            # make it Hermitian). It has following four cases: (ignore the phase factor)
            # (I+X@P_2...P_k)|0...0> = |0...0> + |1>|\psi>
            # (I+Y@P_2...P_k)|0...0> = |0...0> + i|1>|\psi>
            # The other forms are not possible in the standard form, by construction.

            # The first case means we need [1,1] vector and controlled gates and in the
            # second case we need [1, i] vector and controlled gates. Corresponding, it is
            # the first column of H and the first column of SH respectively.

            # For the other stabilizers, the process can be repeated, as by definition they
            # commute.

            if self.M[r][r] == 'Y' or self.M[r][r] == 'Z':
                circuit.append(cirq.S(qubits[r]))

            for n in range(self.n):
                if n == r:
                    continue
                if self.M[r][n] == 'I':
                    continue
                op = gate_dict[self.M[r][n]]
                circuit.append(
                    cirq.ControlledOperation([qubits[r]], op(qubits[n])))
        # At this stage, the state vector should be equal to equations 3.17 and 3.18.

        return circuit
コード例 #16
0
        prefix = gates[:i + 1]
        expected_a = cirq.LinearCombinationOfGates(collections.Counter(prefix))
        expected_b = -expected_a

        assert_linear_combinations_are_equal(a, expected_a)
        assert_linear_combinations_are_equal(b, expected_b)


@pytest.mark.parametrize('op', (
    cirq.X(q0),
    cirq.Y(q1),
    cirq.XX(q0, q1),
    cirq.CZ(q0, q1),
    cirq.FREDKIN(q0, q1, q2),
    cirq.ControlledOperation((q0, q1), cirq.H(q2)),
    cirq.ParallelGateOperation(cirq.X, (q0, q1, q2)),
    cirq.PauliString({
        q0: cirq.X,
        q1: cirq.Y,
        q2: cirq.Z
    }),
))
def test_empty_linear_combination_of_operations_accepts_all_operations(op):
    combination = cirq.LinearCombinationOfOperations({})
    combination[op] = -0.5j
    assert len(combination) == 1


@pytest.mark.parametrize('terms', (
    {
コード例 #17
0
    def construct_controlled_circuit(self, choice=True):
        """
        :param choice: The value on which to condition: True = |1>, False = |0>
        :return:
        """
        moments = []
        for i in range(int(math.log2(len(self.A)))):
            number_of_blocks = 2**i
            step = len(self.A) // number_of_blocks
            n = math.ceil(len(self.A) / (2 * number_of_blocks))
            for j in range(2**i):
                l = int(self.bin_C[j * step:(2 * j + 1) * n][::-1], 2)
                # First comes the incrementer from figure 5
                moments += ShorIncrementer(
                    self.A[(2 * j + 1) * n:(2 * j + 1) * n + n],
                    self.A[j * step:(2 * j + 1) * n],
                    ctrl=self.garbage).construct_circuit().moments

                # Then the set of CNOTs from figure 5
                moments += [
                    cirq.CNOT(self.garbage, k)
                    for k in self.A[(2 * j + 1) * n:(2 * j + 1) * n + n]
                ]

                # Afterwards the Carry operation from figure 5 to see if wen need to increment Xh
                moments += ShorCarryGate(a=self.A[j * step:(2 * j + 1) * n], c=l,
                                         g=self.A[(2 * j + 1) * n:(2 * j + 1) * n + n - 1],
                                         ancilla=self.garbage, control=self.control) \
                    .construct_controlled_circuit(choice).moments

                # Then the incrementer controlled by the result of the Carry operation
                moments += ShorIncrementer(
                    self.A[(2 * j + 1) * n:(2 * j + 1) * n + n],
                    self.A[j * step:(2 * j + 1) * n],
                    self.garbage).construct_circuit().moments

                # Reset the carry_result qubit to its original value
                moments += ShorCarryGate(
                    a=self.A[j * step:(2 * j + 1) * n],
                    c=l,
                    g=self.A[(2 * j + 1) * n:(2 * j + 1) * n + n - 1],
                    ancilla=self.garbage,
                    control=self.control).construct_controlled_circuit(
                        choice).moments

                # lastly the CNOTs
                moments += [
                    cirq.CNOT(self.garbage, k)
                    for k in self.A[(2 * j + 1) * n:(2 * j + 1) * n + n]
                ]

        circuit = cirq.Circuit()

        # Last layer is the 1-bit addition
        for i in range(len(self.bin_C)):
            if self.bin_C[i] == '1':
                if choice:
                    # moments += [cirq.CNOT(self.control, self.A[i])]
                    moments += [
                        cirq.ControlledOperation(self.control,
                                                 cirq.X(self.A[i]))
                    ]
                else:
                    moments += [
                        cirq.ControlledOperation(self.control,
                                                 cirq.X(self.A[i]),
                                                 control_values=[0] *
                                                 len(self.control))
                    ]
        circuit.append(moments)
        return circuit
コード例 #18
0
def test_bounded_effect():
    qubits = cirq.LineQubit.range(2)
    cy = cirq.ControlledOperation(qubits[0], cirq.Y(qubits[1]))
    assert cirq.trace_distance_bound(cy**0.001) < 0.01
コード例 #19
0
def test_controlled_operation_is_consistent(gate: cirq.GateOperation):
    cb = cirq.NamedQubit('ctr')
    cgate = cirq.ControlledOperation(cb, gate)
    cirq.testing.assert_implements_consistent_protocols(cgate)
コード例 #20
0
ファイル: json_test.py プロジェクト: c-poole/Cirq
 cirq.CCNOT,
 'CCX':
 cirq.CCX,
 'CCXPowGate':
 cirq.CCXPowGate(exponent=0.123, global_shift=0.456),
 'CCZ':
 cirq.CCZ,
 'CCZPowGate':
 cirq.CCZPowGate(exponent=0.123, global_shift=0.456),
 'CNOT':
 cirq.CNOT,
 'CNotPowGate':
 cirq.CNotPowGate(exponent=0.123, global_shift=0.456),
 'ControlledOperation':
 cirq.ControlledOperation(sub_operation=cirq.Y(cirq.NamedQubit('target')),
                          controls=cirq.LineQubit.range(2),
                          control_values=[0, 1]),
 'ControlledGate':
 cirq.ControlledGate(sub_gate=cirq.Y,
                     num_controls=2,
                     control_values=[0, 1],
                     control_qid_shape=(3, 2)),
 'CX':
 cirq.CX,
 'CSWAP':
 cirq.CSWAP,
 'CSwapGate':
 cirq.CSwapGate(),
 'CZ':
 cirq.CZ,
 'CZPowGate':
コード例 #21
0
def test_controlled_mixture():
    a, b = cirq.LineQubit.range(2)
    c_yes = cirq.ControlledOperation(controls=[b], sub_operation=cirq.phase_flip(0.25).on(a))
    assert cirq.has_mixture(c_yes)
    assert cirq.approx_eq(cirq.mixture(c_yes), [(0.75, np.eye(4)), (0.25, cirq.unitary(cirq.CZ))])
コード例 #22
0
 def controlled_by(
     self,
     *control_qubits: 'cirq.Qid',
     control_values: Optional[Sequence[Union[int, Collection[int]]]] = None,
 ) -> 'cirq.Operation':
     return cirq.ControlledOperation(control_qubits, self, control_values)
コード例 #23
0
    def construct_controlled_circuit(self, choice):

        # The choice parameter will serve to choose between adding c or N-c
        n = len(self.a)
        b = bin(self.c)[2:].zfill(n)[::-1]
        circuit = cirq.Circuit()

        # Particular cases (Not defined in the paper)
        # Please double check them
        if len(self.a) == 1:
            if b[0] == '1':
                if choice:
                    circuit.append(
                        cirq.TOFFOLI(self.control, self.a[0], self.ancilla))
                else:
                    circuit.append(
                        cirq.ControlledOperation([self.control, self.a[0]],
                                                 cirq.X(self.ancilla),
                                                 control_values=[0, 1]))
            return circuit
        elif len(self.a) == 2:
            if b[1] == '1':
                if choice:
                    circuit.append(
                        cirq.TOFFOLI(self.control, self.a[1], self.ancilla))
                    circuit.append(cirq.CNOT(self.control, self.a[1]))
                else:
                    circuit.append(
                        cirq.ControlledOperation([self.control, self.a[1]],
                                                 cirq.X(self.ancilla),
                                                 control_values=[0, 1]))
                    circuit.append(
                        cirq.ControlledOperation([self.control],
                                                 cirq.X(self.a[1]),
                                                 control_values=[0]))
            if b[0] == '1':
                if choice:
                    circuit.append(
                        cirq.ControlledOperation(
                            [self.control, self.a[0], self.a[1]],
                            cirq.X(self.ancilla),
                            control_values=[1, 1, 1]))
                else:
                    circuit.append(
                        cirq.ControlledOperation(
                            [self.control, self.a[0], self.a[1]],
                            cirq.X(self.ancilla),
                            control_values=[0, 1, 1]))
            if b[1] == '1':
                if choice:
                    circuit.append(cirq.CNOT(self.control, self.a[1]))
                else:
                    circuit.append(
                        cirq.ControlledOperation([self.control],
                                                 cirq.X(self.a[1]),
                                                 control_values=[0]))
            return circuit

        # If the (choice == True) the operation will carried if the control qubit is equal to 1
        # Otherwise it will be done if the control qubit is equal to 0
        if choice:
            moment1 = [cirq.TOFFOLI(self.control, self.g[-1], self.ancilla)]
        else:
            moment1 = [
                cirq.ControlledOperation([self.control, self.g[-1]],
                                         cirq.X(self.ancilla),
                                         control_values=[0, 1])
            ]

        if b[0] == '1':
            moments = [cirq.TOFFOLI(self.a[0], self.a[1], self.g[0])]
        else:
            moments = []

        moment3 = []

        if b[1] == '1':
            moments += [cirq.X(self.a[1]), cirq.CNOT(self.a[1], self.g[0])]
        for i in range(2, n):
            moments += [cirq.TOFFOLI(self.g[i - 2], self.a[i], self.g[i - 1])]
            moment3 += [cirq.TOFFOLI(self.g[i - 2], self.a[i], self.g[i - 1])]
            if b[i] == '1':
                moments += [
                    cirq.X(self.a[i]),
                    cirq.CNOT(self.a[i], self.g[i - 1])
                ]
        circuit.append(moment1)
        circuit.append(moments[::-1])
        circuit.append(moment3)
        circuit.append(moment1)
        circuit.append(moment3[::-1])
        circuit.append(moments)
        return circuit