def testCSIGNtoCNOT(self): """ CSIGN to CNOT: compare unitary matrix for CSIGN and product of resolved matrices in terms of CNOT. """ qc1 = QubitCircuit(2) qc1.add_gate("CSIGN", targets=[1], controls=[0]) U1 = gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates(basis="CNOT") U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def testCNOTtoSQRTSWAP(self): """ CNOT to SQRTSWAP: compare unitary matrix for CNOT and product of resolved matrices in terms of SQRTSWAP. """ qc1 = QubitCircuit(2) qc1.add_gate("CNOT", targets=[0], controls=[1]) U1 = gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates(basis="SQRTSWAP") U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def testadjacentgates(self): """ Adjacent Gates: compare unitary matrix for ISWAP and product of resolved matrices in terms of adjacent gates interaction. """ qc1 = QubitCircuit(3) qc1.add_gate("ISWAP", targets=[0, 2]) U1 = gate_sequence_product(qc1.propagators()) qc0 = qc1.adjacent_gates() qc2 = qc0.resolve_gates(basis="ISWAP") U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def test_linear_SQRTISWAP(self): """ Linear Spin Chain Setup: compare unitary matrix for SQRTISWAP and propogator matrix of the implemented physical model. """ N = 3 qc = QubitCircuit(N) qc.add_gate("SQRTISWAP", targets=[0, 1]) U_ideal = gate_sequence_product(qc.propagators()) p = LinearSpinChain(N, correct_global_phase=True) U_list = p.run(qc) U_physical = gate_sequence_product(U_list) assert_((U_ideal - U_physical).norm() < 1e-12)
def skip_dispersivecqed_SQRTISWAP(self): """ Dispersive cQED Setup: compare unitary matrix for SQRTISWAP and propogator matrix of the implemented physical model. """ N = 3 qc1 = QubitCircuit(N) qc1.add_gate("SQRTISWAP", targets=[0, 1]) U_ideal = gate_sequence_product(qc1.propagators()) p = DispersivecQED(N, correct_global_phase=True) U_list = p.run(qc1) U_physical = gate_sequence_product(U_list) print((U_ideal - U_physical).norm()) assert_((U_ideal - U_physical).norm() < 1e-4)
def test_add_gate(self): """ Addition of a gate object directly to a `QubitCircuit` """ qc = QubitCircuit(3) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("RZ", targets=[1], arg_value = 1.570796, arg_label="P") qc.add_gate(test_gate) # Test explicit gate addition assert_(qc.gates[0].name == "CNOT") assert_(qc.gates[0].targets == [1]) assert_(qc.gates[0].controls == [0]) # Test direct gate addition assert_(qc.gates[1].name == test_gate.name) assert_(qc.gates[1].targets == test_gate.targets) assert_(qc.gates[1].controls == test_gate.controls)
def testCNOTtoISWAP(self): """ CNOT to ISWAP: compare unitary matrix for CNOT and product of resolved matrices in terms of ISWAP. """ qc1 = QubitCircuit(2) qc1.add_gate("CNOT", targets=[0], controls=[1]) U1 = gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates(basis="ISWAP") U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def testISWAPtoCNOT(self): """ ISWAP to CNOT: compare unitary matrix for ISWAP and product of resolved matrices in terms of CNOT. """ qc1 = QubitCircuit(2) qc1.add_gate("ISWAP", targets=[0, 1]) U1 = gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates(basis="CNOT") U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def testSNOTdecompose(self): """ SNOT to rotation: compare unitary matrix for SNOT and product of resolved matrices in terms of rotation gates. """ qc1 = QubitCircuit(1) qc1.add_gate("SNOT", targets=0) U1 = gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates() U2 = gate_sequence_product(qc2.propagators()) assert_((U1 - U2).norm() < 1e-12)
def testFREDKINdecompose(self): """ FREDKIN to rotation and CNOT: compare unitary matrix for FREDKIN and product of resolved matrices in terms of rotation gates and CNOT. """ qc1 = QubitCircuit(3) qc1.add_gate("FREDKIN", targets=[0, 1], controls=[2]) U1 = gates.gate_sequence_product(qc1.propagators()) qc2 = qc1.resolve_gates() U2 = gates.gate_sequence_product(qc2.propagators()) assert _op_dist(U1, U2) < 1e-12
def local(para, N): qc = QubitCircuit(N) shape = (N, 3) para = para.reshape(shape) i = 0 for angles in para: qc.add_gate("RZ", i, None, angles[0]) qc.add_gate("RX", i, None, angles[1]) qc.add_gate("RZ", i, None, angles[2]) i += 1 return qc
def test_multi_gates(self): N = 2 H_d = tensor([sigmaz()] * 2) H_c = [] test = OptPulseProcessor(N) test.add_drift(H_d, [0, 1]) test.add_control(sigmax(), cyclic_permutation=True) test.add_control(sigmay(), cyclic_permutation=True) test.add_control(tensor([sigmay(), sigmay()])) # qubits circuit with 3 gates setting_args = { "SNOT": { "num_tslots": 10, "evo_time": 1 }, "SWAP": { "num_tslots": 30, "evo_time": 3 }, "CNOT": { "num_tslots": 30, "evo_time": 3 } } qc = QubitCircuit(N) qc.add_gate("SNOT", 0) qc.add_gate("SWAP", targets=[0, 1]) qc.add_gate('CNOT', controls=1, targets=[0]) test.load_circuit(qc, setting_args=setting_args, merge_gates=False) rho0 = rand_ket(4) # use random generated ket state rho0.dims = [[2, 2], [1, 1]] U = gate_sequence_product(qc.propagators()) rho1 = U * rho0 result = test.run_state(rho0) assert_(fidelity(result.states[-1], rho1) > 1 - 1.0e-6)
def testadjacentgates(self): """ Adjacent Gates: compare unitary matrix for ISWAP and product of resolved matrices in terms of adjacent gates interaction. """ qc1 = QubitCircuit(3) qc1.add_gate("ISWAP", targets=[0, 2]) U1 = gates.gate_sequence_product(qc1.propagators()) qc0 = qc1.adjacent_gates() qc2 = qc0.resolve_gates(basis="ISWAP") U2 = gates.gate_sequence_product(qc2.propagators()) assert _op_dist(U1, U2) < 1e-12
def test_linear_combination(self): """ Linear Spin Chain Setup: compare unitary matrix for ISWAP, SQRTISWAP, RX and RY gates and the propogator matrix of the implemented physical model. """ N = 3 qc = QubitCircuit(N) qc.add_gate("ISWAP", targets=[0, 1]) qc.add_gate("SQRTISWAP", targets=[0, 1]) qc.add_gate("RZ", arg_value=np.pi/2, arg_label=r"\pi/2", targets=[1]) qc.add_gate("RX", arg_value=np.pi/2, arg_label=r"\pi/2", targets=[0]) U_ideal = gate_sequence_product(qc.propagators()) p = LinearSpinChain(N, correct_global_phase=True) U_list = p.run(qc) U_physical = gate_sequence_product(U_list) assert_((U_ideal - U_physical).norm() < 1e-12)
def qft_gate_sequence(N=1, swapping=True): """ Quantum Fourier Transform operator on N qubits returning the gate sequence. Parameters ---------- N: int Number of qubits. swap: boolean Flag indicating sequence of swap gates to be applied at the end or not. Returns ------- qc: instance of QubitCircuit Gate sequence of Hadamard and controlled rotation gates implementing QFT """ if N < 1: raise ValueError("Minimum value of N can be 1") qc = QubitCircuit(N) if N == 1: qc.add_gate("SNOT", targets=[0]) else: for i in range(N): for j in range(i): qc.add_gate(r"CPHASE", targets=[j], controls=[i], arg_label=r"{\pi/2^{%d}}" % (i - j), arg_value=np.pi/(2**(i-j))) qc.add_gate("SNOT", targets=[i]) if swapping == True: for i in range(N//2): qc.add_gate(r"SWAP", targets=[i], controls=[N-1-i]) return qc
def test_compiler_with_continous_pulse(spline_kind, schedule_mode): num_qubits = 2 circuit = QubitCircuit(num_qubits) circuit.add_gate("X", targets=0) circuit.add_gate("X", targets=1) circuit.add_gate("X", targets=0) processor = CircularSpinChain(num_qubits) gauss_compiler = MyCompiler( processor.N, processor.params, processor.pulse_dict) processor.load_circuit( circuit, schedule_mode = schedule_mode, compiler=gauss_compiler) result = processor.run_state(init_state = basis([2,2], [0,0])) assert(abs(fidelity(result.states[-1],basis([2,2],[0,1])) - 1) < 1.e-6)
def test_user_gate(self): """ User defined gate for QubitCircuit """ def customer_gate1(arg_values): mat = np.zeros((4, 4), dtype=np.complex128) mat[0, 0] = mat[1, 1] = 1. mat[2:4, 2:4] = gates.rx(arg_values) return Qobj(mat, dims=[[2, 2], [2, 2]]) def customer_gate2(): mat = np.array([[1., 0], [0., 1.j]]) return Qobj(mat, dims=[[2], [2]]) qc = QubitCircuit(3) qc.user_gates = {"CTRLRX": customer_gate1, "T1": customer_gate2} qc.add_gate("CTRLRX", targets=[1, 2], arg_value=np.pi / 2) qc.add_gate("T1", targets=[1]) props = qc.propagators() result1 = tensor(identity(2), customer_gate1(np.pi / 2)) np.testing.assert_allclose(props[0], result1) result2 = tensor(identity(2), customer_gate2(), identity(2)) np.testing.assert_allclose(props[1], result2)
def test_analytical_evo(self): """ Test of run_state with exp(-iHt) """ N = 3 qc = QubitCircuit(N) qc.add_gate("ISWAP", targets=[0, 1]) qc.add_gate("RZ", arg_value=np.pi / 2, arg_label=r"\pi/2", targets=[1]) qc.add_gate("RX", arg_value=np.pi / 2, arg_label=r"\pi/2", targets=[0]) U_ideal = gate_sequence_product(qc.propagators()) rho0 = rand_ket(2**N) rho0.dims = [[2] * N, [1] * N] rho1 = gate_sequence_product([rho0] + qc.propagators()) p = DispersivecQED(N, correct_global_phase=True) U_list = p.run_state(rho0=rho0, qc=qc, analytical=True) result = gate_sequence_product(U_list) assert_allclose(fidelity(result, rho1), 1., rtol=1e-2, err_msg="Analytical run_state fails in DispersivecQED")
def test_dispersivecqed_combination(self): """ Dispersive cQED Setup: compare unitary matrix for ISWAP, SQRTISWAP, RX and RY gates and the propogator matrix of the implemented physical model. """ N = 3 qc1 = QubitCircuit(N) qc1.add_gate("ISWAP", targets=[0, 1]) qc1.add_gate("RZ", arg_value=np.pi/2, arg_label=r"\pi/2", targets=[1]) qc1.add_gate("RX", arg_value=np.pi/2, arg_label=r"\pi/2", targets=[0]) U_ideal = gate_sequence_product(qc1.propagators()) p = DispersivecQED(N, correct_global_phase=True) U_list = p.run(qc1) U_physical = gate_sequence_product(U_list) print((U_ideal - U_physical).norm()) assert_((U_ideal - U_physical).norm() < 1e-2)
def test_add_gate(self): """ Addition of a gate object directly to a `QubitCircuit` """ qc = QubitCircuit(3) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("RZ", targets=[1], arg_value=1.570796, arg_label="P") qc.add_gate(test_gate) # Test explicit gate addition assert_(qc.gates[0].name == "CNOT") assert_(qc.gates[0].targets == [1]) assert_(qc.gates[0].controls == [0]) # Test direct gate addition assert_(qc.gates[1].name == test_gate.name) assert_(qc.gates[1].targets == test_gate.targets) assert_(qc.gates[1].controls == test_gate.controls)
def test_N_level_system(self): """ Test for circuit with N-level system. """ mat3 = rand_dm(3, density=1.) def controlled_mat3(arg_value): """ A qubit control an operator acting on a 3 level system """ control_value = arg_value dim = mat3.dims[0][0] return (tensor(fock_dm(2, control_value), mat3) + tensor(fock_dm(2, 1 - control_value), identity(dim))) qc = QubitCircuit(2, dims=[3, 2]) qc.user_gates = {"CTRLMAT3": controlled_mat3} qc.add_gate("CTRLMAT3", targets=[1, 0], arg_value=1) props = qc.propagators() np.testing.assert_allclose(mat3, ptrace(props[0], 0) - 1)
def evolute(state): CNOT01 = Gate('CNOT', targets=1, controls=0) CNOT12 = Gate('CNOT', targets=2, controls=1) CNOT02 = Gate('CNOT', targets=2, controls=0) H0 = Gate('SNOT', targets=0) sqrtX0 = Gate('SQRTNOT', targets=0) H2 = Gate('SNOT', targets=2) qc = QubitCircuit(N=3) # qc.add_gate(sqrtX0) # qc.add_gate(sqrtX0) qc.add_gate(CNOT01) qc.add_gate(H0) # qc.add_gate(CNOT12) # qc.add_gate(H2) # qc.add_gate(CNOT02) # qc.add_gate(H2) gates_sequence = qc.propagators() scheme = oper.gate_sequence_product(gates_sequence) return scheme * state
def test_add_gate(self): """ Addition of a gate object directly to a `QubitCircuit` """ qc = QubitCircuit(6) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("SWAP", targets=[1, 4]) qc.add_gate(test_gate) qc.add_gate("TOFFOLI", controls=[0, 1], targets=[2]) qc.add_gate("SNOT", targets=[3]) qc.add_gate(test_gate, index=[3]) qc.add_1q_gate("RY", start=4, end=5, arg_value=1.570796) # Test explicit gate addition assert qc.gates[0].name == "CNOT" assert qc.gates[0].targets == [1] assert qc.gates[0].controls == [0] # Test direct gate addition assert qc.gates[1].name == test_gate.name assert qc.gates[1].targets == test_gate.targets # Test specified position gate addition assert qc.gates[3].name == test_gate.name assert qc.gates[3].targets == test_gate.targets # Test adding 1 qubit gate on [start, end] qubits assert qc.gates[5].name == "RY" assert qc.gates[5].targets == [4] assert qc.gates[5].arg_value == 1.570796 assert qc.gates[6].name == "RY" assert qc.gates[6].targets == [5] assert qc.gates[5].arg_value == 1.570796 # Test Exceptions # Global phase is not included for gate in _single_qubit_gates: if gate not in _para_gates: # No target pytest.raises(ValueError, qc.add_gate, gate, None, None) # Multiple targets pytest.raises(ValueError, qc.add_gate, gate, [0, 1, 2], None) # With control pytest.raises(ValueError, qc.add_gate, gate, [0], [1]) else: # No target pytest.raises(ValueError, qc.add_gate, gate, None, None, 1) # Multiple targets pytest.raises(ValueError, qc.add_gate, gate, [0, 1, 2], None, 1) # With control pytest.raises(ValueError, qc.add_gate, gate, [0], [1], 1) for gate in _ctrl_gates: if gate not in _para_gates: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1]) # No control pytest.raises(ValueError, qc.add_gate, gate, [0], None) else: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1], 1) # No control pytest.raises(ValueError, qc.add_gate, gate, [0], None, 1) for gate in _swap_like: if gate not in _para_gates: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], None) # With control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], [3]) else: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], None, 1) # With control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], [3], 1) for gate in _fredkin_like: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], [2]) # No control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], None) for gate in _toffoli_like: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1, 2]) # Single control pytest.raises(ValueError, qc.add_gate, gate, [0], [1])
def test_reverse(self): """ Reverse a quantum circuit """ qc = QubitCircuit(3) qc.add_gate("RX", targets=[0], arg_value=3.141, arg_label=r"\pi/2") qc.add_gate("CNOT", targets=[1], controls=[0]) qc.add_gate("SNOT", targets=[2]) # Keep input output same qc.add_state("0", targets=[0]) qc.add_state("+", targets=[1], state_type="output") qc.add_state("-", targets=[1]) qc.reverse_circuit() assert_(qc.gates[2].name == "SNOT") assert_(qc.gates[1].name == "CNOT") assert_(qc.gates[0].name == "RX") assert_(qc.input_states[0] == "0") assert_(qc.input_states[2] == None) assert_(qc.output_states[1] == "+")
def adjacent_gates(self, qc, setup="linear"): """ Method to resolve 2 qubit gates with non-adjacent control/s or target/s in terms of gates with adjacent interactions for linear/circular spin chain system. Parameters ---------- qc: :class:`.QubitCircuit` The circular spin chain circuit to be resolved setup: Boolean Linear of Circular spin chain setup Returns ------- qc: :class:`.QubitCircuit` Returns QubitCircuit of resolved gates for the qubit circuit in the desired basis. """ # FIXME This huge block has been here for a long time. # It could be moved to the new compiler section and carefully # splitted into smaller peaces. qc_t = QubitCircuit(qc.N, qc.reverse_states) swap_gates = ["SWAP", "ISWAP", "SQRTISWAP", "SQRTSWAP", "BERKELEY", "SWAPalpha"] N = qc.N for gate in qc.gates: if gate.name == "CNOT" or gate.name == "CSIGN": start = min([gate.targets[0], gate.controls[0]]) end = max([gate.targets[0], gate.controls[0]]) if (setup == "linear" or (setup == "circular" and (end - start) <= N // 2)): i = start while i < end: if (start + end - i - i == 1 and (end - start + 1) % 2 == 0): # Apply required gate if control and target are # adjacent to each other, provided |control-target| # is even. if end == gate.controls[0]: qc_t.add_gate(gate.name, targets=[i], controls=[i + 1]) else: qc_t.add_gate(gate.name, targets=[i + 1], controls=[i]) elif (start + end - i - i == 2 and (end - start + 1) % 2 == 1): # Apply a swap between i and its adjacent gate, # then the required gate if and then another swap # if control and target have one qubit between # them, provided |control-target| is odd. qc_t.add_gate("SWAP", targets=[i, i + 1]) if end == gate.controls[0]: qc_t.add_gate(gate.name, targets=[i + 1], controls=[i + 2]) else: qc_t.add_gate(gate.name, targets=[i + 2], controls=[i + 1]) qc_t.add_gate("SWAP", [i, i + 1]) i += 1 else: # Swap the target/s and/or control with their # adjacent qubit to bring them closer. qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate("SWAP", [start + end - i - 1, start + end - i]) i += 1 elif (end - start) < N - 1: """ If the resolving has to go backwards, the path is first mapped to a separate circuit and then copied back to the original circuit. """ temp = QubitCircuit(N - end + start) i = 0 while i < (N - end + start): if (N + start - end - i - i == 1 and (N - end + start + 1) % 2 == 0): if end == gate.controls[0]: temp.add_gate(gate.name, targets=[i], controls=[i + 1]) else: temp.add_gate(gate.name, targets=[i + 1], controls=[i]) elif (N + start - end - i - i == 2 and (N - end + start + 1) % 2 == 1): temp.add_gate("SWAP", targets=[i, i + 1]) if end == gate.controls[0]: temp.add_gate(gate.name, targets=[i + 2], controls=[i + 1]) else: temp.add_gate(gate.name, targets=[i + 1], controls=[i + 2]) temp.add_gate("SWAP", [i, i + 1]) i += 1 else: temp.add_gate("SWAP", [i, i + 1]) temp.add_gate("SWAP", [N + start - end - i - 1, N + start - end - i]) i += 1 j = 0 for gate in temp.gates: if (j < N - end - 2): if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, end + gate.targets[0], end + gate.controls[0]) else: qc_t.add_gate(gate.name, [end + gate.targets[0], end + gate.targets[1]]) elif (j == N - end - 2): if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, end + gate.targets[0], (end + gate.controls[0]) % N) else: qc_t.add_gate(gate.name, [end + gate.targets[0], (end + gate.targets[1]) % N]) else: if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, (end + gate.targets[0]) % N, (end + gate.controls[0]) % N) else: qc_t.add_gate(gate.name, [(end + gate.targets[0]) % N, (end + gate.targets[1]) % N]) j = j + 1 elif (end - start) == N - 1: qc_t.add_gate(gate.name, gate.targets, gate.controls) elif gate.name in swap_gates: start = min([gate.targets[0], gate.targets[1]]) end = max([gate.targets[0], gate.targets[1]]) if (setup == "linear" or (setup == "circular" and (end - start) <= N // 2)): i = start while i < end: if (start + end - i - i == 1 and (end - start + 1) % 2 == 0): qc_t.add_gate(gate.name, [i, i + 1]) elif ((start + end - i - i) == 2 and (end - start + 1) % 2 == 1): qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate(gate.name, [i + 1, i + 2]) qc_t.add_gate("SWAP", [i, i + 1]) i += 1 else: qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate("SWAP", [start + end - i - 1, start + end - i]) i += 1 else: temp = QubitCircuit(N - end + start) i = 0 while i < (N - end + start): if (N + start - end - i - i == 1 and (N - end + start + 1) % 2 == 0): temp.add_gate(gate.name, [i, i + 1]) elif (N + start - end - i - i == 2 and (N - end + start + 1) % 2 == 1): temp.add_gate("SWAP", [i, i + 1]) temp.add_gate(gate.name, [i + 1, i + 2]) temp.add_gate("SWAP", [i, i + 1]) i += 1 else: temp.add_gate("SWAP", [i, i + 1]) temp.add_gate("SWAP", [N + start - end - i - 1, N + start - end - i]) i += 1 j = 0 for gate in temp.gates: if(j < N - end - 2): qc_t.add_gate(gate.name, [end + gate.targets[0], end + gate.targets[1]]) elif(j == N - end - 2): qc_t.add_gate(gate.name, [end + gate.targets[0], (end + gate.targets[1]) % N]) else: qc_t.add_gate(gate.name, [(end + gate.targets[0]) % N, (end + gate.targets[1]) % N]) j = j + 1 else: qc_t.add_gate(gate.name, gate.targets, gate.controls, gate.arg_value, gate.arg_label) return qc_t
def test_single_qubit_gates(self): """ Text single qubit gates are added correctly """ qc = QubitCircuit(3) qc.add_gate("X", targets=[0]) qc.add_gate("CY", targets=[1], controls=[0]) qc.add_gate("Y", targets=[2]) qc.add_gate("CS", targets=[0], controls=[1]) qc.add_gate("Z", targets=[1]) qc.add_gate("CT", targets=[2], controls=[2]) qc.add_gate("CZ", targets=[0], controls=[0]) qc.add_gate("S", targets=[1]) qc.add_gate("T", targets=[2]) assert qc.gates[8].name == "T" assert qc.gates[7].name == "S" assert qc.gates[6].name == "CZ" assert qc.gates[5].name == "CT" assert qc.gates[4].name == "Z" assert qc.gates[3].name == "CS" assert qc.gates[2].name == "Y" assert qc.gates[1].name == "CY" assert qc.gates[0].name == "X" assert qc.gates[8].targets == [2] assert qc.gates[7].targets == [1] assert qc.gates[6].targets == [0] assert qc.gates[5].targets == [2] assert qc.gates[4].targets == [1] assert qc.gates[3].targets == [0] assert qc.gates[2].targets == [2] assert qc.gates[1].targets == [1] assert qc.gates[0].targets == [0] assert qc.gates[6].controls == [0] assert qc.gates[5].controls == [2] assert qc.gates[3].controls == [1] assert qc.gates[1].controls == [0]
def test_add_measurement(self): """ Addition of Measurement Object to a circuit. """ qc = QubitCircuit(3, num_cbits=2) qc.add_measurement("M0", targets=[0], classical_store=1) qc.add_gate("CNOT", targets=[1], controls=[0]) qc.add_gate("TOFFOLI", controls=[0, 1], targets=[2]) qc.add_measurement("M1", targets=[2], classical_store=0) qc.add_gate("SNOT", targets=[1], classical_controls=[0, 1]) qc.add_measurement("M2", targets=[1]) # checking correct addition of measurements assert qc.gates[0].targets[0] == 0 assert qc.gates[0].classical_store == 1 assert qc.gates[3].name == "M1" assert qc.gates[5].classical_store is None # checking if gates are added correctly with measurements assert qc.gates[2].name == "TOFFOLI" assert qc.gates[4].classical_controls == [0, 1]
from qutip import * from qutip.qip.circuit import QubitCircuit from diamond.DiamondCircuit import save_circuit import numpy as np qc = QubitCircuit(4, reverse_states=False) qc.add_gate('X', 0) qc.add_gate('X', 1) qc.add_gate('R_z', 2, [0, 1, 3], 0, r'\mp \frac{\pi}{2}') qc.add_gate('R_y', 2, [0, 1, 3], 0, r'a') qc.add_gate('R_z', 2, [0, 1, 3], 0, r'b') qc.add_gate('A', [0, 1, 2, 3]) qc.add_gate('R_z', 2, [0, 1, 3], 0, r'\mp \frac{\pi}{2}') qc.add_gate('R_y', 2, [0, 1, 3], 0, r'a') qc.add_gate('R_z', 2, [0, 1, 3], 0, r'c') qc.add_gate('B', [0, 1, 2, 3]) qc.add_gate('R_z', 3, [0, 1, 2], 0, r'\pm \frac{\pi}{2}') qc.add_gate('R_y', 3, [0, 1, 2], 0, r'a') qc.add_gate('R_z', 3, [0, 1, 2], 0, r'-b') qc.add_gate('C', [0, 1, 2, 3]) qc.add_gate('R_z', 1, [0, 2, 3], 0, r'\pm \frac{\pi}{2}') qc.add_gate('R_y', 1, [0, 2, 3], 0, r'a') qc.add_gate('R_z', 1, [0, 2, 3], 0, r'-c') qc.add_gate('D', [0, 1, 2, 3]) qc.add_gate('R_z', 3, [0, 1, 2], 0, r'\mp a') qc.add_gate('R_y', 3, [0, 1, 2], 0, r'-\pi') qc.add_gate('R_z', 3, [0, 1, 2], 0, r'\pm a') qc.add_gate(r'R_{\phi}', 3, [0, 1, 2], 0, r't - \pi') qc.add_gate('X', 1) qc.add_gate('X', 2) save_circuit(qc, 'U')
def adjacent_gates(self, qc, setup="linear"): """ Method to resolve 2 qubit gates with non-adjacent control/s or target/s in terms of gates with adjacent interactions for linear/circular spin chain system. Parameters ---------- qc: QubitCircuit The circular spin chain circuit to be resolved setup: Boolean Linear of Circular spin chain setup Returns ---------- qc: QubitCircuit Returns QubitCircuit of resolved gates for the qubit circuit in the desired basis. """ qc_t = QubitCircuit(qc.N, qc.reverse_states) swap_gates = ["SWAP", "ISWAP", "SQRTISWAP", "SQRTSWAP", "BERKELEY", "SWAPalpha"] N = qc.N for gate in qc.gates: if gate.name == "CNOT" or gate.name == "CSIGN": start = min([gate.targets[0], gate.controls[0]]) end = max([gate.targets[0], gate.controls[0]]) if (setup == "linear" or (setup == "circular" and (end - start) <= N // 2)): i = start while i < end: if (start + end - i - i == 1 and (end - start + 1) % 2 == 0): # Apply required gate if control and target are # adjacent to each other, provided |control-target| # is even. if end == gate.controls[0]: qc_t.add_gate(gate.name, targets=[i], controls=[i + 1]) else: qc_t.add_gate(gate.name, targets=[i + 1], controls=[i]) elif (start + end - i - i == 2 and (end - start + 1) % 2 == 1): # Apply a swap between i and its adjacent gate, # then the required gate if and then another swap # if control and target have one qubit between # them, provided |control-target| is odd. qc_t.add_gate("SWAP", targets=[i, i + 1]) if end == gate.controls[0]: qc_t.add_gate(gate.name, targets=[i + 1], controls=[i + 2]) else: qc_t.add_gate(gate.name, targets=[i + 2], controls=[i + 1]) qc_t.add_gate("SWAP", [i, i + 1]) i += 1 else: # Swap the target/s and/or control with their # adjacent qubit to bring them closer. qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate("SWAP", [start + end - i - 1, start + end - i]) i += 1 elif (end - start) < N - 1: """ If the resolving has to go backwards, the path is first mapped to a separate circuit and then copied back to the original circuit. """ temp = QubitCircuit(N - end + start) i = 0 while i < (N - end + start): if (N + start - end - i - i == 1 and (N - end + start + 1) % 2 == 0): if end == gate.controls[0]: temp.add_gate(gate.name, targets=[i], controls=[i + 1]) else: temp.add_gate(gate.name, targets=[i + 1], controls=[i]) elif (N + start - end - i - i == 2 and (N - end + start + 1) % 2 == 1): temp.add_gate("SWAP", targets=[i, i + 1]) if end == gate.controls[0]: temp.add_gate(gate.name, targets=[i + 2], controls=[i + 1]) else: temp.add_gate(gate.name, targets=[i + 1], controls=[i + 2]) temp.add_gate("SWAP", [i, i + 1]) i += 1 else: temp.add_gate("SWAP", [i, i + 1]) temp.add_gate("SWAP", [N + start - end - i - 1, N + start - end - i]) i += 1 j = 0 for gate in temp.gates: if (j < N - end - 2): if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, end + gate.targets[0], end + gate.controls[0]) else: qc_t.add_gate(gate.name, [end + gate.targets[0], end + gate.targets[1]]) elif (j == N - end - 2): if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, end + gate.targets[0], (end + gate.controls[0]) % N) else: qc_t.add_gate(gate.name, [end + gate.targets[0], (end + gate.targets[1]) % N]) else: if gate.name in ["CNOT", "CSIGN"]: qc_t.add_gate(gate.name, (end + gate.targets[0]) % N, (end + gate.controls[0]) % N) else: qc_t.add_gate(gate.name, [(end + gate.targets[0]) % N, (end + gate.targets[1]) % N]) j = j + 1 elif (end - start) == N - 1: qc_t.add_gate(gate.name, gate.targets, gate.controls) elif gate.name in swap_gates: start = min([gate.targets[0], gate.targets[1]]) end = max([gate.targets[0], gate.targets[1]]) if (setup == "linear" or (setup == "circular" and (end - start) <= N // 2)): i = start while i < end: if (start + end - i - i == 1 and (end - start + 1) % 2 == 0): qc_t.add_gate(gate.name, [i, i + 1]) elif ((start + end - i - i) == 2 and (end - start + 1) % 2 == 1): qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate(gate.name, [i + 1, i + 2]) qc_t.add_gate("SWAP", [i, i + 1]) i += 1 else: qc_t.add_gate("SWAP", [i, i + 1]) qc_t.add_gate("SWAP", [start + end - i - 1, start + end - i]) i += 1 else: temp = QubitCircuit(N - end + start) i = 0 while i < (N - end + start): if (N + start - end - i - i == 1 and (N - end + start + 1) % 2 == 0): temp.add_gate(gate.name, [i, i + 1]) elif (N + start - end - i - i == 2 and (N - end + start + 1) % 2 == 1): temp.add_gate("SWAP", [i, i + 1]) temp.add_gate(gate.name, [i + 1, i + 2]) temp.add_gate("SWAP", [i, i + 1]) i += 1 else: temp.add_gate("SWAP", [i, i + 1]) temp.add_gate("SWAP", [N + start - end - i - 1, N + start - end - i]) i += 1 j = 0 for gate in temp.gates: if(j < N - end - 2): qc_t.add_gate(gate.name, [end + gate.targets[0], end + gate.targets[1]]) elif(j == N - end - 2): qc_t.add_gate(gate.name, [end + gate.targets[0], (end + gate.targets[1]) % N]) else: qc_t.add_gate(gate.name, [(end + gate.targets[0]) % N, (end + gate.targets[1]) % N]) j = j + 1 else: qc_t.add_gate(gate.name, gate.targets, gate.controls, gate.arg_value, gate.arg_label) return qc_t
def test_add_circuit(self): """ Addition of a circuit to a `QubitCircuit` """ qc = QubitCircuit(6) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("SWAP", targets=[1, 4]) qc.add_gate(test_gate) qc.add_gate("TOFFOLI", controls=[0, 1], targets=[2]) qc.add_gate("SNOT", targets=[3]) qc.add_gate(test_gate, index=[3]) qc.add_measurement("M0", targets=[0], classical_store=[1]) qc.add_1q_gate("RY", start=4, end=5, arg_value=1.570796) qc1 = QubitCircuit(6) qc1.add_circuit(qc) # Test if all gates and measurements are added assert len(qc1.gates) == len(qc.gates) for i in range(len(qc1.gates)): assert (qc1.gates[i].name == qc.gates[i].name) assert (qc1.gates[i].targets == qc.gates[i].targets) if (isinstance(qc1.gates[i], Gate) and isinstance(qc.gates[i], Gate)): assert (qc1.gates[i].controls == qc.gates[i].controls) assert (qc1.gates[i].classical_controls == qc.gates[i].classical_controls) elif (isinstance(qc1.gates[i], Measurement) and isinstance(qc.gates[i], Measurement)): assert (qc1.gates[i].classical_store == qc.gates[i].classical_store) # Test exception when qubit out of range pytest.raises(NotImplementedError, qc1.add_circuit, qc, start=4) qc2 = QubitCircuit(8) qc2.add_circuit(qc, start=2) # Test if all gates are added assert len(qc2.gates) == len(qc.gates) # Test if the positions are correct for i in range(len(qc2.gates)): if qc.gates[i].targets is not None: assert (qc2.gates[i].targets[0] == qc.gates[i].targets[0]+2) if (isinstance(qc.gates[i], Gate) and qc.gates[i].controls is not None): assert (qc2.gates[i].controls[0] == qc.gates[i].controls[0]+2)
def testStateParams(a1, a2, a3, a4, a5, a6): QC = QubitCircuit(3) QC.add_gate("RX", targets=0, arg_value=a1) QC.add_gate("RX", targets=1, arg_value=a2) QC.add_gate("RX", targets=2, arg_value=a3) QC.add_gate("CNOT", targets=1, controls=0) QC.add_gate("CNOT", targets=2, controls=0) QC.add_gate("RX", targets=0, arg_value=a4) QC.add_gate("RX", targets=1, arg_value=a5) QC.add_gate("RX", targets=2, arg_value=a6) U_list = QC.propagators() finalGate = gate_sequence_product(U_list) finalState = finalGate * initialState return calcStateFidelity(targetState, finalState)
def test_add_state(self): """ Addition of input and output states to a circuit. """ qc = QubitCircuit(3) qc.add_state("0", targets=[0]) qc.add_state("+", targets=[1], state_type="output") qc.add_state("-", targets=[1]) assert qc.input_states[0] == "0" assert qc.input_states[2] is None assert qc.output_states[1] == "+" qc1 = QubitCircuit(10) qc1.add_state("0", targets=[2, 3, 5, 6]) qc1.add_state("+", targets=[1, 4, 9]) qc1.add_state("A", targets=[1, 4, 9], state_type="output") qc1.add_state("A", targets=[1, 4, 9], state_type="output") qc1.add_state("beta", targets=[0], state_type="output") assert qc1.input_states[0] is None assert qc1.input_states[2] == "0" assert qc1.input_states[3] == "0" assert qc1.input_states[6] == "0" assert qc1.input_states[1] == "+" assert qc1.input_states[4] == "+" assert qc1.output_states[2] is None assert qc1.output_states[1] == "A" assert qc1.output_states[4] == "A" assert qc1.output_states[9] == "A" assert qc1.output_states[0] == "beta"
from .three_q_generators import * from numpy import pi from qutip.qip.operations import snot from qutip.qip.circuit import QubitCircuit from qutip.qip.operations import gate_sequence_product from qutip.tensor import tensor import qutip as qt spins = [] for i in range(1, 4): spins.append(qt.basis(2, 0)) initial_state = tensor(spins) QC = QubitCircuit(3) QC.add_gate("RX", targets=0, arg_value=0.5) QC.add_gate("RX", targets=1, arg_value=0.1) QC.add_gate("RX", targets=2, arg_value=0.2223472) QC.add_gate("CNOT", targets=1, controls=0) QC.add_gate("CNOT", targets=2, controls=0) QC.add_gate("RX", targets=0, arg_value=0.26127) QC.add_gate("RX", targets=1, arg_value=1.3942948) QC.add_gate("RX", targets=1, arg_value=0.4378) U_list = QC.propagators() TargetGate = gate_sequence_product(U_list) class threeQubitCircuit(problem): def __init__(self,
def test_exceptions(self, gate): """ Text exceptions are thrown correctly for inadequate inputs """ qc = QubitCircuit(2) pytest.raises(ValueError, qc.add_gate, gate, targets=[1], controls=[0])
def _circuit1(): circuit1 = QubitCircuit(6) circuit1.add_gate("SNOT", 2) circuit1.add_gate("CNOT", 4, 2) circuit1.add_gate("CNOT", 3, 2) circuit1.add_gate("CNOT", 1, 2) circuit1.add_gate("CNOT", 5, 4) circuit1.add_gate("CNOT", 1, 5) circuit1.add_gate("SWAP", [0, 1]) return circuit1
def test_reverse(self): """ Reverse a quantum circuit """ qc = QubitCircuit(3) qc.add_gate("RX", targets=[0], arg_value=3.141, arg_label=r"\pi/2") qc.add_gate("CNOT", targets=[1], controls=[0]) qc.add_measurement("M1", targets=[1]) qc.add_gate("SNOT", targets=[2]) # Keep input output same qc.add_state("0", targets=[0]) qc.add_state("+", targets=[1], state_type="output") qc.add_state("-", targets=[1]) qc_rev = qc.reverse_circuit() assert qc_rev.gates[0].name == "SNOT" assert qc_rev.gates[1].name == "M1" assert qc_rev.gates[2].name == "CNOT" assert qc_rev.gates[3].name == "RX" assert qc_rev.input_states[0] == "0" assert qc_rev.input_states[2] is None assert qc_rev.output_states[1] == "+"
def _circuit2(): circuit2 = QubitCircuit(8) circuit2.add_gate("SNOT", 1) circuit2.add_gate("SNOT", 2) circuit2.add_gate("SNOT", 3) circuit2.add_gate("CNOT", 4, 5) circuit2.add_gate("CNOT", 4, 6) circuit2.add_gate("CNOT", 3, 4) circuit2.add_gate("CNOT", 3, 5) circuit2.add_gate("CNOT", 3, 7) circuit2.add_gate("CNOT", 2, 4) circuit2.add_gate("CNOT", 2, 6) circuit2.add_gate("CNOT", 2, 7) circuit2.add_gate("CNOT", 1, 5) circuit2.add_gate("CNOT", 1, 6) circuit2.add_gate("CNOT", 1, 7) return circuit2
def _teleportation_circuit(): teleportation = QubitCircuit(3, num_cbits=2, input_states=["q0", "0", "0", "c0", "c1"]) teleportation.add_gate("SNOT", targets=[1]) teleportation.add_gate("CNOT", targets=[2], controls=[1]) teleportation.add_gate("CNOT", targets=[1], controls=[0]) teleportation.add_gate("SNOT", targets=[0]) teleportation.add_measurement("M0", targets=[0], classical_store=1) teleportation.add_measurement("M1", targets=[1], classical_store=0) teleportation.add_gate("X", targets=[2], classical_controls=[0]) teleportation.add_gate("Z", targets=[2], classical_controls=[1]) return teleportation
def _instructions1(): circuit3 = QubitCircuit(6) circuit3.add_gate("SNOT", 0) circuit3.add_gate("SNOT", 1) circuit3.add_gate("CNOT", 2, 3) circuit3.add_gate("CNOT", 1, 2) circuit3.add_gate("CNOT", 1, 0) circuit3.add_gate("SNOT", 3) circuit3.add_gate("CNOT", 1, 3) circuit3.add_gate("CNOT", 1, 3) instruction_list = [] for gate in circuit3.gates: if gate.name == "SNOT": instruction_list.append(Instruction(gate, duration=1)) else: instruction_list.append(Instruction(gate, duration=2)) return instruction_list
def evolute(state): qc = QubitCircuit(N=3) qc.add_gate("CNOT", controls=0, targets=1) qc.add_gate("SNOT", targets=0) U_list = qc.propagators() return gate_sequence_product(U_list) * state
def test_add_state(self): """ Addition of input and output states to a circuit. """ qc = QubitCircuit(3) qc.add_state("0", targets=[0]) qc.add_state("+", targets=[1], state_type="output") qc.add_state("-", targets=[1]) assert_(qc.input_states[0] == "0") assert_(qc.input_states[2] == None) assert_(qc.output_states[1] == "+") qc1 = QubitCircuit(10) qc1.add_state("0", targets=[2, 3, 5, 6]) qc1.add_state("+", targets=[1,4,9]) qc1.add_state("A", targets=[1,4,9], state_type="output") qc1.add_state("A", targets=[1,4,9], state_type="output") qc1.add_state("beta", targets=[0], state_type="output") assert_(qc1.input_states[0] == None) assert_(qc1.input_states[2] == "0") assert_(qc1.input_states[3] == "0") assert_(qc1.input_states[6] == "0") assert_(qc1.input_states[1] == "+") assert_(qc1.input_states[4] == "+") assert_(qc1.output_states[2] == None) assert_(qc1.output_states[1] == "A") assert_(qc1.output_states[4] == "A") assert_(qc1.output_states[9] == "A") assert_(qc1.output_states[0] == "beta")