def test_circuit_extract_produces_circuit(self): random.seed(SEED) g = cliffordT(6, 60, 0.15) clifford_simp(g, quiet=True) circuit_extract(g) # This should not result in an exception Circuit.from_graph(g)
def test_magic_state_decomposition_is_correct(self): c = Circuit(6) for i in range(6): c.add_gate("T", i) g = c.to_graph() gsum = replace_magic_states(g) self.assertTrue(np.allclose(g.to_tensor(), gsum.to_tensor()))
def test_two_qubit_gate_semantics(self): c = Circuit(2) c.add_gate("CNOT", 0, 1) cnot_matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) self.assertTrue(compare_tensors(c.to_matrix(), cnot_matrix)) c = Circuit(2) c.add_gate("CZ", 0, 1) cz_matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]]) self.assertTrue(compare_tensors(c.to_matrix(), cz_matrix))
def test_teleport_reduce(self): """Tests whether teleport_reduce preserves semantics on a set of circuits that have been broken before.""" for i,s in enumerate([qasm_1,qasm_2,qasm_3,qasm_4]): with self.subTest(i=i): c = qasm(s) g = c.to_graph() c2 = Circuit.from_graph(teleport_reduce(g)) self.assertTrue(c.verify_equality(c2))
def test_cliffordT_preserves_graph_semantics(self): random.seed(SEED) g = cliffordT(4, 20, 0.2) c = Circuit.from_graph(g) g2 = c.to_graph() t = tensorfy(g, False) t2 = tensorfy(g2, False) self.assertTrue(compare_tensors(t, t2, False))
def test_circuit_extract_preserves_semantics(self): random.seed(SEED) g = cliffordT(5, 70, 0.15) t = g.to_tensor() clifford_simp(g, quiet=True) circuit_extract(g) t2 = Circuit.from_graph(g).to_tensor() self.assertTrue(compare_tensors(t,t2))
def test_cliffords_preserves_graph_semantics(self): random.seed(SEED) g = cliffords(5,30) c = Circuit.from_graph(g) g2 = c.to_graph() t = tensorfy(g) t2 = tensorfy(g2) self.assertTrue(compare_tensors(t,t2))
def to_qasm(self): if self.compiled_program is None: return super().to_qasm() circuit = Circuit(self.n_qubits) comments = [] for g in self.compiled_program: if isinstance(g, Pragma): wiring = " ".join(["//", g.command, "["+g.freeform_string[2:-1]+"]"]) comments.append(wiring) elif isinstance(g, Gate): if g.name == "CZ": circuit.add_gate("CZ", g.qubits[0].index, g.qubits[1].index) elif g.name == "RX": circuit.add_gate("XPhase", g.qubits[0].index, g.params[0]) elif g.name == "RZ": circuit.add_gate("ZPhase", g.qubits[0].index, g.params[0]) else: print("Unsupported gate found!", g) qasm = circuit.to_qasm() return '\n'.join(comments+[qasm])
def test_three_cnots_is_swap(self): g = Graph() i1 = g.add_vertex(0, 0, 0) i2 = g.add_vertex(0, 1, 0) o1 = g.add_vertex(0, 0, 1) o2 = g.add_vertex(0, 1, 1) g.inputs = [i1, i2] g.outputs = [o1, o2] g.add_edges([(i1, o2), (i2, o1)]) swap = tensorfy(g) c = Circuit(2) c.add_gate("CNOT", 0, 1) c.add_gate("CNOT", 1, 0) c.add_gate("CNOT", 0, 1) three_cnots = tensorfy(c.to_graph()) self.assertTrue(compare_tensors(swap, three_cnots))
def build_random_parity_map(qubits, n_cnots, circuit=None): """ Builds a random parity map. :param qubits: The number of qubits that participate in the parity map :param n_cnots: The number of CNOTs in the parity map :param circuit: A (list of) circuit object(s) that implements a row_add() method to add the generated CNOT gates [optional] :return: a 2D numpy array that represents the parity map. """ if circuit is None: circuit = [] if not isinstance(circuit, list): circuit = [circuit] g = generate_cnots(qubits=qubits, depth=n_cnots) c = Circuit.from_graph(g) matrix = Mat2.id(qubits) for gate in c.gates: matrix.row_add(gate.control, gate.target) for c in circuit: c.row_add(gate.control, gate.target) return matrix.data
def test_cz_optimize_extract(self): qb_no = 8 c = Circuit(qb_no) for i in range(qb_no): for j in range(i + 1, qb_no): c.add_gate("CZ", i, j) g = c.to_graph() clifford_simp(g, quiet=True) c2 = extract_circuit(g) cnot_count = 0 for gate in c2.gates: if isinstance(gate, CNOT): cnot_count += 1 self.assertTrue(cnot_count == 4) self.assertTrue(c.verify_equality(c2))
def apply(self, program, accelerator, options): # Import qiskit modules here so that users # who don't have qiskit can still use rest of xacc from pyzx.circuit import Circuit from pyzx import simplify, extract, optimize # Map CompositeInstruction program to OpenQasm string openqasm_compiler = xacc.getCompiler('staq') src = openqasm_compiler.translate(program).replace('\\','') measures = [] lines = src.split('\n') for l in lines: if 'measure' in l or 'creg' in l: measures.append(l) c = Circuit.from_qasm(src) g = c.to_graph() simplify.full_reduce(g,quiet=True) c2 = extract.extract_circuit(g) c3 = optimize.basic_optimization(c2.to_basic_gates()) c3 = c3.to_basic_gates() c3 = c3.split_phase_gates() output = c3.to_qasm() for measure in measures: output += '\n' + measure # Map the output to OpenQasm and map to XACC IR out_prog = openqasm_compiler.compile(output, accelerator).getComposites()[0] # update the given program CompositeInstruction reference program.clear() for inst in out_prog.getInstructions(): program.addInstruction(inst) return
def dag_to_pyzx_circuit(dag: DAGCircuit) -> Translated: """Build a ``QuantumCircuit`` object from a ``DAGCircuit``. Args: dag (DAGCircuit): the input dag. Return: QuantumCircuit: the circuit representing the input dag. """ # In Qiskit, the quantum registers can have many diff names, whereas in PyZX circuit, there is only one global qubits. # We need a mapping from the global qubits back to the named qubits pyreg_range_to_qreg = dict( ) # map the start idx of the named qreg to the qreg qreg_to_pyreg_range = dict( ) # maps the qreg name to the start idx of global qreg tot_qb_count = 0 qregs = OrderedDict() for qreg in dag.qregs.values(): qreg_tmp = QuantumRegister(qreg.size, name=qreg.name) qregs[qreg.name] = qreg_tmp pyreg_range_to_qreg[tot_qb_count] = qreg qreg_to_pyreg_range[qreg.name] = tot_qb_count tot_qb_count += qreg.size cregs = OrderedDict() for creg in dag.cregs.values(): creg_tmp = ClassicalRegister(creg.size, name=creg.name) cregs[creg.name] = creg_tmp gates = [] for node in dag.topological_op_nodes(): # collects the qregs qubits = [ qreg_to_pyreg_range[qubit.register.name] + qubit.index for qubit in node.qargs ] # collects the cregs, which is passed (without conversion) to PyZX clbits = [] for clbit in node.cargs: clbits.append(cregs[clbit.register.name][clbit.index]) # if node.condition is not None: # raise NotImplementedError(f"Classical control is not supported by PyZX") inst = node.op if check_classical_control(inst, qubits, gates, clbits=clbits, condition=node.condition): pass else: to_pyzx_gate(inst, qubits, gates, clbits=clbits, condition=node.condition) name = '' if dag.name is None else str(dag.name) circuit = Circuit(tot_qb_count, name=name) circuit.gates = gates return Translated(circuit, qreg_to_pyreg_range, pyreg_range_to_qreg, list(qregs.values()), list(cregs.values()))
def test_verify_equality_permutation_option(self): c1 = Circuit(2) c2 = Circuit(2) c2.add_gate("SWAP", 0, 1) self.assertTrue(c1.verify_equality(c2, up_to_swaps=True)) self.assertFalse(c1.verify_equality(c2, up_to_swaps=False))
def test_to_quipper_and_back(self): s = self.c.to_quipper() c2 = Circuit.from_quipper(s) self.assertEqual(self.c.qubits, c2.qubits) self.assertListEqual(self.c.gates, c2.gates)
def from_qasm_file(fname): circuit = Circuit.from_qasm_file(fname) return CNOT_tracker.from_circuit(circuit)
def test_to_graph_and_back(self): g = self.c.to_graph() c2 = Circuit.from_graph(g) self.assertEqual(self.c.qubits, c2.qubits) self.assertListEqual(self.c.gates,c2.gates)
def setUp(self): c = Circuit(3) c.add_gate("CNOT",0,1) c.add_gate("S",2) c.add_gate("CNOT",2,1) self.c = c