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)
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))
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)))