def fromCircuit(circuit, initial_qubit_placement=None, final_qubit_placement=None): if isinstance(circuit, TketCircuit): circuit = tk_to_pyzx(circuit) zphases = {} current_parities = mat22partition(Mat2.id(circuit.qubits)) if initial_qubit_placement is not None: current_parities = ["".join([row[i] for i in initial_qubit_placement]) for row in current_parities] for gate in circuit.gates: parity = current_parities[gate.target] if gate.name in ["CNOT", "CX"]: # Update current_parities control = current_parities[gate.control] current_parities[gate.target] = "".join([str((int(i)+int(j))%2) for i,j in zip(control, parity)]) elif isinstance(gate, ZPhase): # Add the T rotation to the phases if parity in zphases: zphases[parity] += gate.phase else: zphases[parity] = gate.phase else: print("Gate not supported!", gate.name) def clamp(phase): new_phase = phase%2 if new_phase > 1: return new_phase -2 return new_phase zphases = {par:clamp(r) for par, r in zphases.items() if clamp(r) != 0} if final_qubit_placement is not None: current_parities = [ current_parities[i] for i in final_qubit_placement] return PhasePoly(zphases, current_parities)
def update_matrix(self): self.matrix = Mat2.id(self.n_qubits) for gate in self.gates: if hasattr(gate, "name") and gate.name == "CNOT": self.matrix.row_add(gate.control, gate.target) else: print("Warning: CNOT tracker can only be used for circuits with only CNOT gates!")
def to_tket(self): if self.out_par != mat22partition(Mat2.id(self.n_qubits)): print(self.out_par) raise NotImplementedError("The linear transformation part of the phase polynomial cannot yet be transformed into a tket circuit") circuit = TketCircuit(self.n_qubits) for parity, phase in self.zphases.items(): qubits = [i for i,s in enumerate(parity) if s == '1'] circuit.add_pauliexpbox(PauliExpBox([Pauli.Z]*len(qubits), phase), qubits) # TODO add the linear combination part with CNOTs Transform.DecomposeBoxes().apply(circuit) return circuit
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 make_random_phase_poly(n_qubits, n_gadgets, return_circuit=False): parities = set() if n_gadgets > 2**n_qubits: n_gadgets=n_qubits^3 if n_qubits < 26: for integer in np.random.choice(2**n_qubits-1, replace=False, size=n_gadgets): parities.add(integer+1) elif n_qubits < 64: while len(parities) < n_gadgets: parities.add(np.random.randint(1, 2**n_qubits)) else: while len(parities) < n_gadgets: parities.add("".join(np.random.choice(["0", "1"], n_qubits, replace=True))) if n_qubits < 64: parities = [("{0:{fill}"+str(n_qubits)+"b}").format(integer, fill='0', align='right') for integer in parities] zphase_dict = {"".join([str(int(i)) for i in p]):Fraction(1,4) for p in parities} out_parities = mat22partition(Mat2.id(n_qubits)) phase_poly = PhasePoly(zphase_dict, out_parities) if return_circuit: return route_phase_poly(phase_poly, create_architecture(FULLY_CONNECTED, n_qubits=n_qubits), do_matroid="arianne") return phase_poly
def __init__(self, n_qubits, **kwargs): super().__init__(n_qubits, **kwargs) self.matrix = Mat2.id(n_qubits) self.row_perm = np.arange(n_qubits) self.col_perm = np.arange(n_qubits) self.n_qubits = n_qubits
def test_inverse(self): inv = self.m4.inverse() self.assertEqual(inv * self.m4, Mat2.id(5)) self.assertEqual(self.m4 * inv, Mat2.id(5))