def test_tensor_gates_two_qubit():
    prog = Program().inst([CNOTgate(0, 1)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
    true_unitary = apply_gate(gate_matrix['CNOT'], [0, 1], 4).toarray()
    assert np.allclose(test_unitary, true_unitary)

    prog = Program().inst([CNOTgate(1, 0)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
    true_unitary = apply_gate(gate_matrix['CNOT'], [1, 0], 4).toarray()
    assert np.allclose(test_unitary, true_unitary)

    prog = Program().inst([CNOTgate(1, 3)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 4).toarray()
    true_unitary = apply_gate(gate_matrix['CNOT'], [1, 3], 4).toarray()
    assert np.allclose(test_unitary, true_unitary)
def test_tensor_gates_single_qubit():
    prog = Program().inst([Hgate(0)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 1).toarray()
    true_unitary = gate_matrix['H']
    assert np.allclose(test_unitary, true_unitary)

    prog = Program().inst([Hgate(0)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
    true_unitary = np.kron(np.eye(2**4), gate_matrix['H'])
    assert np.allclose(test_unitary, true_unitary)

    prog = Program().inst([RXgate(0.2, 3)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
    true_unitary = np.kron(np.eye(2**1), np.kron(gate_matrix['RX'](0.2),  np.eye(2**3)))
    assert np.allclose(test_unitary, true_unitary)

    prog = Program().inst([RXgate(0.5, 4)])
    test_unitary = tensor_gates(gate_matrix, {}, prog.instructions[0], 5).toarray()
    true_unitary = np.kron(np.eye(2**0), np.kron(gate_matrix['RX'](0.5),  np.eye(2**4)))
    assert np.allclose(test_unitary, true_unitary)
예제 #3
0
    def transition(self, instruction):
        """
        Implements a transition on the unitary-qvm.

        :param Gate instruction: QuilAction gate to be implemented
        """
        if instruction.name in self.gate_set or instruction.name in self.defgate_set:
            # get the unitary and evolve the state
            unitary = tensor_gates(self.gate_set, self.defgate_set,
                                   instruction, self.num_qubits)
            self.umat = unitary.dot(self.umat)
            self.program_counter += 1
        else:
            raise TypeError("Gate {} is not in the "
                            "gate set".format(instruction.name))
예제 #4
0
    def _transition(self, instruction):
        """
        Implements a transition on the wf-qvm.
        Assumes entire Program() is already loaded into self.program as
        the synthesized list of Quilbase action objects.

        Possible types of instructions:
            Measurement
            gate in self.gate_set or self.defgates_set
            Jump, JumpTarget, JumpConditional
            Unary and Binary ClassicalInstruction

        :param action-like instruction: {Measurement, Instr, Jump, JumpTarget,
            JumpTarget, JumpConditional, UnaryClassicalInstruction,
            BinaryClassicalInstruction, Halt} instruction to execute.
        """
        if isinstance(instruction, Measurement):
            # perform measurement and modify wf in-place
            t_qbit = value_get(instruction.qubit)
            t_cbit = value_get(instruction.classical_reg)
            measured_val, unitary = self.measurement(t_qbit, psi=None)
            self.wf = unitary.dot(self.wf)

            # load measured value into classical bit destination
            self.classical_memory[t_cbit] = measured_val
            self.program_counter += 1

        elif isinstance(instruction, Gate):
            # apply Gate or DefGate
            unitary = tensor_gates(self.gate_set, self.defgate_set,
                                   instruction, self.num_qubits)
            self.wf = unitary.dot(self.wf)
            self.program_counter += 1

        elif isinstance(instruction, Jump):
            # unconditional Jump; go directly to Label
            self.program_counter = self.find_label(instruction.target)

        elif isinstance(instruction, JumpTarget):
            # Label; pass straight over
            self.program_counter += 1

        elif isinstance(instruction, JumpConditional):
            # JumpConditional; check classical reg
            cond = self.classical_memory[value_get(instruction.condition)]
            dest_index = self.find_label(instruction.target)
            if isinstance(instruction, JumpWhen):
                jump_if_cond = True
            elif isinstance(instruction, JumpUnless):
                jump_if_cond = False
            else:
                raise TypeError("Invalid JumpConditional")

            if not (cond ^ jump_if_cond):
                # jumping: set prog counter to JumpTarget
                self.program_counter = dest_index
            else:
                # not jumping: hop over this JumpConditional
                self.program_counter += 1

        elif isinstance(instruction, UnaryClassicalInstruction):
            # UnaryClassicalInstruction; set classical reg
            target_ind = value_get(instruction.target)
            old = self.classical_memory[target_ind]
            if isinstance(instruction, ClassicalTrue):
                new = True
            elif isinstance(instruction, ClassicalFalse):
                new = False
            elif isinstance(instruction, ClassicalNot):
                new = not old
            else:
                raise TypeError("Invalid UnaryClassicalInstruction")

            self.classical_memory[target_ind] = new
            self.program_counter += 1

        elif isinstance(instruction, BinaryClassicalInstruction):
            # BinaryClassicalInstruction; compute and set classical reg
            left_ind = value_get(instruction.left)
            left_val = self.classical_memory[left_ind]
            right_ind = value_get(instruction.right)
            right_val = self.classical_memory[right_ind]
            if isinstance(instruction, ClassicalAnd):
                # compute LEFT AND RIGHT, set RIGHT to the result
                self.classical_memory[right_ind] = left_val & right_val
            elif isinstance(instruction, ClassicalOr):
                # compute LEFT OR RIGHT, set RIGHT to the result
                self.classical_memory[right_ind] = left_val | right_val
            elif isinstance(instruction, ClassicalMove):
                # move LEFT to RIGHT
                self.classical_memory[right_ind] = left_val
            elif isinstance(instruction, ClassicalExchange):
                # exchange LEFT and RIGHT
                self.classical_memory[left_ind] = right_val
                self.classical_memory[right_ind] = left_val
            else:
                raise TypeError("Invalid BinaryClassicalInstruction")

            self.program_counter += 1
        elif isinstance(instruction, Halt):
            # do nothing; set program_counter to end of program
            self.program_counter = len(self.program)
        else:
            raise TypeError("Invalid / unsupported instruction type: {}\n"
                            "Currently supported: unary/binary classical "
                            "instructions, control flow (if/while/jumps), "
                            "measurements, and gates/defgates.".format(
                                type(instruction)))