def prog(sample): p = pq.Program(n_qubits) n_features = len(sample) for j in range(n_qubits): p.inst(RY(np.arcsin(sample[j % n_features])), j) p.inst(RZ(np.arccos(sample[j % n_features]**2)), j) return p
def output_prog(theta): p = pq.Program(n_qubits) theta = theta.reshape(3, n_qubits, depth) for i in range(depth): p += ising_prog for j in range(n_qubits): rj = n_qubits - j - 1 p.inst(RX(theta[0, rj, i]), j) p.inst(RZ(theta[1, rj, i]), j) p.inst(RX(theta[2, rj, i]), j) return p
def ising_prog_gen(trotter_steps, T, n_qubits): """ Generates Quil program evolving system according to fully connected transverse Ising hamiltionian. The exponential of a sum of non-commuting Pauli operators is generated by Trotter Suzuki approximation of first order (Lie product formula). Important: The generation of matrix exponential could be done only on quantum computer simulator. :param trotter_steps: (int) trotter steps. :param T: (int) evolution time. :param n_qubits: (int) number of qubits in a circuit. :return (Program) Quil program evolving system according to fully connected transverse Ising hamiltionian. """ # Initilize coefficients h_coeff = np.random.uniform(-1.0, 1.0, size=n_qubits) J_coeff = dict() for val in itertools.combinations(range(n_qubits), 2): J_coeff[val] = np.random.uniform(-1.0, 1.0) # Unitary for steps in range(trotter_steps): non_inter = [ linalg.expm( -(1j) * T / trotter_steps * multi_kron(*[h * X if i == j else I for i in range(n_qubits)])) for j, h in enumerate(h_coeff) ] inter = [ linalg.expm(-(1j) * T / trotter_steps * multi_kron(*[ J * Z if i == k[0] else Z if i == k[1] else I for i in range(n_qubits) ])) for k, J in J_coeff.items() ] ising_step = multi_dot(*non_inter + inter) if steps == 0: ising_gate = ising_step else: ising_gate = multi_dot(ising_step, ising_gate) ising_prog = pq.Program(n_qubits) ising_prog.inst(ising_gate) return ising_prog
def grad_prog(theta, idx, sign): theta = theta.reshape(3, n_qubits, depth) idx = np.unravel_index(idx, theta.shape) p = pq.Program(n_qubits) for i in range(depth): p += ising_prog for j in range(n_qubits): rj = n_qubits - j - 1 if idx == (0, rj, i): p.inst(RX(sign * np.pi / 2.0), j) p.inst(RX(theta[0, rj, i]), j) if idx == (1, rj, i): p.inst(RZ(sign * np.pi / 2.0), j) p.inst(RZ(theta[1, rj, i]), j) if idx == (2, rj, i): p.inst(RX(sign * np.pi / 2.0), j) p.inst(RX(theta[2, rj, i]), j) return p
def input_prog(sample): p = pq.Program(n_qubits) for j in range(n_qubits): p.inst(RY(np.arcsin(sample[0])), j) p.inst(RZ(np.arccos(sample[0]**2)), j) return p
#============================================================================== # Quantum Circuit Learning - Regression #============================================================================== from qsimulator import Z from qcl import QCL state_generators = dict() state_generators['input'] = input_prog state_generators['output'] = output_prog state_generators['grad'] = grad_prog initial_theta = np.random.uniform(0.0, 2 * np.pi, size=3 * n_qubits * depth) operator = pq.Program(n_qubits) operator.inst(Z, 0) operator_programs = [operator] est = QCL(state_generators, initial_theta, loss="mean_squared_error", operator_programs=operator_programs, epochs=20, batch_size=m, verbose=True) est.fit(X, y) results = est.get_results() X_test = np.linspace(-1.0, 1.0, 50) y_pred = est.predict(X_test)