def update_qc( nb_qubits, depth=1): # compute the circuit, with CNOT and single qubit gates global gate_number, gate_apply circuit = qtn.Circuit(N=nb_qubits) def entangle_layer(circ): """ Creates a linear entangeling layer""" for ii in range(0, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1) for ii in range(1, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1) def apply_rotation_gates(n, d, qubit): gate_number = operations[n * d + qubit] e = '{}'.format(gate_number) q = 'gate_apply=gate' + e + '.copy()' exec(q, globals(), globals()) b = len(gate_apply) for l in range(0, b, 1): x = gate_apply[l] circuit.apply_gate(x, qubit) def last_rotation_layer(n, qubit): gate_number = operations[n] e = '{}'.format(gate_number) q = 'gate_last=gate' + e + '.copy()' exec(q, globals(), globals()) c = len(gate_last) for l in range(0, c, 1): x = gate_last[l] circuit.apply_gate(x, qubit) for d in range(depth): for ii in range(nb_qubits): # gate_number= operations[nb_qubits * d + i] # exec(f'gate_to_apply= gate{gate_number}') # b=len(gate_to_apply) # for l in range(0,b,1): # x=gate_to_apply[l] # circuit.apply_gate(x, i) apply_rotation_gates(nb_qubits, d, ii) entangle_layer(circuit) for j in range(nb_qubits * depth, nb_qubits + nb_qubits * depth): for i in range(nb_qubits): last_rotation_layer(j, i) # gate_number= operations[j] # exec(f'gate_to_apply_last= gate{gate_number}') # c=len(gate_to_apply_last) # for l in range(0,c,1): # x=gate_to_apply_last[j] # circuit.apply_gate(x, iii) # x = operations[j] # circuit.apply_gate(x, iii) return circuit
def test_prepare_GHZ(self): qc = qtn.Circuit(3) gates = [ ('H', 0), ('H', 1), ('CNOT', 1, 2), ('CNOT', 0, 2), ('H', 0), ('H', 1), ('H', 2), ] qc.apply_circuit(gates) assert qu.expec(qc.psi.to_dense(), qu.ghz_state(3)) == pytest.approx(1)
def random_circuit(nb_qubits, depth=1): # global gate_numbers, gates_apply circuit = qtn.Circuit(N=nb_qubits) def entangle_layer(circ, gate_round=None): """ Creates a linear entangeling layer""" for ii in range(0, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1, gate_round=gate_round) for ii in range(1, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1, gate_round=gate_round) def apply_rotation_gates(n, d, qubit, gate_round=None): gate_numbers = operations_random[n * d + qubit] e = '{}'.format(gate_numbers) q = 'gates_apply=gate' + e + '.copy()' exec(q, globals(), globals()) b = len(gates_apply) for l in range(0, b, 1): x = gates_apply[l] circuit.apply_gate(x, qubit, gate_round=gate_round) def last_rotation_layer(n, qubit, gate_round=None): gate_numbers = operations_random[n] e = '{}'.format(gate_numbers) q = 'gate_last=gate' + e + '.copy()' exec(q, globals(), globals()) c = len(gate_last) for l in range(0, c, 1): x = gate_last[l] circuit.apply_gate(x, qubit, gate_round=gate_round) def U3_gates(qubit, gate_round=None): circuit.apply_gate('U3', 0, 0, 0, qubit, gate_round=gate_round) for d in range(depth): for ii in range(nb_qubits): apply_rotation_gates(nb_qubits, d, ii, gate_round=d) U3_gates(ii, gate_round=d) entangle_layer(circuit, gate_round=d) for j in range(nb_qubits * depth, nb_qubits + nb_qubits * depth): for i in range(nb_qubits): last_rotation_layer(j, i, gate_round=depth) U3_gates(i, gate_round=depth) return circuit
def qcnewcircuit(nb_qubits, depth): """ Creates a new random 'cliffod' circuit""" Warning("Currently only makes a reduced Clifford circuit") global op_list op_list = [] # Construct circuit circuit = qtn.Circuit(N=nb_qubits) # Need to increase the gate set here... maybe this isn't the best way # Might need to use u3 params instead, but this will do for now # gate_list = ['H', 'X', 'Y', # 'Z', 'IDEN', 'S'] def entangle_layer(circ): """ Creates a linear entangeling layer""" for ii in range(0, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1) for ii in range(1, nb_qubits - 1, 2): circ.apply_gate('CNOT', ii, ii + 1) def rotaiton_layer(circ): """ Creates a layer of single qubit rotations based on the list 'single_rotatoins'""" # random_points = np.random.randint( # 0, len(gate_list), circ.num_qubits) for ii in range(nb_qubits): # for random_number in cliff_gates: random_number = random.choice(cliff_gates) exec(f'random_gate= gate{random_number}', globals(), globals()) op_list.append(random_number) x = len(random_gate) for j in range(x): gate = random_gate[j] circ.apply_gate(gate, ii) # Apply first rotation layer (else CX layer does nothing) rotaiton_layer(circuit) # Loop though and alternate rotation and entangelment layers for ii in range(depth): entangle_layer(circuit) rotaiton_layer(circuit) return circuit
def Target_circuit(): """ Generate the circuit of the target state """ qc = qtn.Circuit(N=n, tags='PSI0') #qc = qtn.Tensor(data=qcc) for i in range(d): for j in range(n): gates(qubit_structure[n * i + j], target_gates[n * i + j], qc) for j in range(0, n - 1, 2): qc.apply_gate('CNOT', j, j + 1, gate_round=1) for j in range(1, n - 1, 2): qc.apply_gate('CNOT', j, j + 1, gate_round=1) #qc.barrier() for i in range(n * d, n * d + n): gates(qubit_structure[i], target_gates[i], qc) return qc
def test_prepare_GHZ(self): qc = qtn.Circuit(3) gates = [ ('H', 0), ('H', 1), ('CNOT', 1, 2), ('CNOT', 0, 2), ('H', 0), ('H', 1), ('H', 2), ] qc.apply_circuit(gates) assert qu.expec(qc.psi.to_dense(), qu.ghz_state(3)) == pytest.approx(1) counts = qc.simulate_counts(1024) assert len(counts) == 2 assert '000' in counts assert '111' in counts assert counts['000'] + counts['111'] == 1024
def Output_circuit(): """ Generate the circuit of the output state """ global energy, t_star P = 0 qc = qtn.Circuit(N=n, tags='PSI0') new_gates = [] Ord_Ga = random.randint(0, g - 1) #Nth gates Ind_Ga = NN(output_gates[Ord_Ga]) for i in range(g): new_gates.append(output_gates[i]) new_gates[Ord_Ga] = Ind_Ga for i in range(d): for j in range(n): gates(qubit_structure[n * i + j], target_gates[n * i + j], qc) for j in range(0, n - 1, 2): qc.apply_gate('CNOT', j, j + 1, gate_round=1) for j in range(1, n - 1, 2): qc.apply_gate('CNOT', j, j + 1, gate_round=1) for i in range(n * d, n * d + n): gates(qubit_structure[i], target_gates[i], qc) psi = qc.to_dense() E = np.real(1 - (psi.H @ target) * (target.H @ psi)) if E < 0.01 and t_star == 0: t_star = counts if E < np.real(energy): P = 1 else: P = math.exp(-Beta * (np.real(E) - np.real(energy))) if random.random() < P: energy = E Energy_matrix.append(np.real(energy)) output_gates[Ord_Ga] = Ind_Ga else: Energy_matrix.append(energy) return qc
import random import quimb.tensor as qtn import quimb as qu %config InlineBackend.figure_formats = ['svg'] # 10 qubits and tag the initial wavefunction tensors circ = qtn.Circuit(N=10, tags='PSI0') # initial layer of hadamards for i in range(10): circ.apply_gate('H', i, gate_round=0) # # 8 rounds of entangling gates for r in range(1, 9): # # # even pairs # for i in range(0, 10, 2): # circ.apply_gate('CNOT', i, i + 1, gate_round=r) # # Y-rotations for i in range(10): circ.apply_gate('RY', 1.234, i, gate_round=r) # # # odd pairs # for i in range(1, 9, 2): # circ.apply_gate('CZ', i, i + 1, gate_round=r) # final layer of hadamards for i in range(10): circ.apply_gate('H', i, gate_round=r + 1)