Example #1
0
    def test_big_gates(self):
        """Test large gates with params"""
        qr = QuantumRegister(6, "q")
        circuit = QuantumCircuit(qr)
        circuit.append(IQP([[6, 5, 3], [5, 4, 5], [3, 5, 1]]), [0, 1, 2])

        desired_vector = [
            1 / math.sqrt(16) * complex(0, 1),
            1 / math.sqrt(8) * complex(1, 0),
            1 / math.sqrt(16) * complex(1, 1),
            0,
            0,
            1 / math.sqrt(8) * complex(1, 2),
            1 / math.sqrt(16) * complex(1, 0),
            0,
        ]

        circuit.initialize(desired_vector, [qr[3], qr[4], qr[5]])
        circuit.unitary([[1, 0], [0, 1]], [qr[0]])
        matrix = np.zeros((4, 4))
        theta = Parameter("theta")
        circuit.append(HamiltonianGate(matrix, theta), [qr[1], qr[2]])
        circuit = circuit.bind_parameters({theta: 1})
        circuit.isometry(np.eye(4, 4), list(range(3, 5)), [])

        self.circuit_drawer(circuit, filename="big_gates.png")
Example #2
0
    def test_big_gates(self):
        """Test large gates with params"""
        filename = self._get_resource_path('test_latex_big_gates.tex')
        qr = QuantumRegister(6, 'q')
        circuit = QuantumCircuit(qr)
        circuit.append(IQP([[6, 5, 3], [5, 4, 5], [3, 5, 1]]), [0, 1, 2])

        desired_vector = [
            1 / math.sqrt(16) * complex(0, 1),
            1 / math.sqrt(8) * complex(1, 0),
            1 / math.sqrt(16) * complex(1, 1),
            0,
            0,
            1 / math.sqrt(8) * complex(1, 2),
            1 / math.sqrt(16) * complex(1, 0),
            0]

        circuit.initialize(desired_vector, [qr[3], qr[4], qr[5]])
        circuit.unitary([[1, 0], [0, 1]], [qr[0]])
        matrix = np.zeros((4, 4))
        theta = Parameter('theta')
        circuit.append(HamiltonianGate(matrix, theta), [qr[1], qr[2]])
        circuit = circuit.bind_parameters({theta: 1})
        circuit.isometry(np.eye(4, 4), list(range(3, 5)), [])

        circuit_drawer(circuit, filename=filename, output='latex_source')

        self.assertEqualToReference(filename)
def ad_hoc_hhl(A, t0, r):
    reg_b = QuantumRegister(2)
    reg_c = QuantumRegister(4)
    ancil = QuantumRegister(1)
    circ = QuantumCircuit(reg_b, reg_c, ancil)
    circ.append(quantum_phase_estimation(2, 4, HamiltonianGate(A, t0 / 16)),
                range(6))
    circ.swap(reg_c[1], reg_c[3])
    for i in range(4):
        circ.cry(np.pi * (2**(4 - i - r)), reg_c[i], ancil[0])
        circ.barrier()
    circ.swap(reg_c[1], reg_c[3])
    circ.append(
        quantum_phase_estimation(2, 4, HamiltonianGate(A, t0 / 16)).inverse(),
        range(6))
    return circ
    def build_varckt(self):

        # Build variational circuit
        circ = QuantumCircuit(self.n)
        circ.h(range(self.n))
        for i in range(self.p):
            eC = QuantumCircuit(self.n,
                                name='$U(C,\\gamma_' + str(i + 1) + ')$')
            eC.append(HamiltonianGate(self.C, self.gamma[i]), range(self.n))
            eB = QuantumCircuit(self.n,
                                name='$U(B,\\beta_' + str(i + 1) + ')$')
            eB.rx(2 * self.beta[i], range(self.n))
            circ.append(eC.to_gate(), range(self.n))
            circ.append(eB.to_gate(), range(self.n))
        circ.measure_all()
        return circ
def hhl_forward_ckt(n, t, m, l, A, t0, vis=False):
    reg_b = QuantumRegister(n, name='b')
    reg_c = QuantumRegister(t, name='c')
    reg_m = QuantumRegister(m, name='m')
    reg_l = QuantumRegister(l, name='l')
    temp = QuantumCircuit(reg_b, name='$U$')
    temp.append(HamiltonianGate(A, t0 / (2**t)), reg_b)
    circ = QuantumCircuit(reg_b, reg_c, reg_m, reg_l, name='$Fwd$')
    circ.append(quantum_phase_estimation(n, t, temp.to_gate(), vis=vis),
                range(n + t))
    circ.h(reg_m)
    circ.h(reg_l)
    for i in range(m):
        circ.rz(t0 / (2**(m - i)), reg_m[i])
    circ.append(subroutine_b(t, m, l, t0, vis=vis), range(n, n + t + m + l))
    if vis:
        circ.draw('mpl', reverse_bits=True, style={'fontsize': 6, 'subfontsize': 3})\
            .suptitle('HHL Forward Computation', fontsize=16)
    return circ.to_gate()
Example #6
0
    def get_loss(
        self,
        hamiltonian: OperatorBase,
        ansatz: QuantumCircuit,
        dt: float,
        current_parameters: np.ndarray,
    ) -> Tuple[Callable[[np.ndarray], float], Optional[Callable[[np.ndarray], np.ndarray]]]:

        """Get a function to evaluate the infidelity between Trotter step and ansatz.

        Args:
            hamiltonian: The Hamiltonian under which to evolve.
            ansatz: The parameterized quantum circuit which attempts to approximate the
                time-evolved state.
            dt: The time step.
            current_parameters: The current parameters.

        Returns:
            A callable to evaluate the infidelity and, if gradients are supported and required,
                a second callable to evaluate the gradient of the infidelity.
        """
        self._validate_setup(skip={"optimizer"})

        # use Trotterization to evolve the current state
        trotterized = ansatz.bind_parameters(current_parameters)

        if isinstance(hamiltonian, MatrixOp):
            evolution_gate = HamiltonianGate(hamiltonian.primitive, time=dt)
        else:
            evolution_gate = PauliEvolutionGate(hamiltonian, time=dt, synthesis=self.evolution)

        trotterized.append(evolution_gate, ansatz.qubits)

        # define the overlap of the Trotterized state and the ansatz
        x = ParameterVector("w", ansatz.num_parameters)
        shifted = ansatz.assign_parameters(current_parameters + x)
        overlap = StateFn(trotterized).adjoint() @ StateFn(shifted)

        converted = self.expectation.convert(overlap)

        def evaluate_loss(
            displacement: Union[np.ndarray, List[np.ndarray]]
        ) -> Union[float, List[float]]:
            """Evaluate the overlap of the ansatz with the Trotterized evolution.

            Args:
                displacement: The parameters for the ansatz.

            Returns:
                The fidelity of the ansatz with parameters ``theta`` and the Trotterized evolution.
            """
            if isinstance(displacement, list):
                displacement = np.asarray(displacement)
                value_dict = {x_i: displacement[:, i].tolist() for i, x_i in enumerate(x)}
            else:
                value_dict = dict(zip(x, displacement))

            sampled = self._sampler.convert(converted, params=value_dict)

            # in principle we could add different loss functions here, but we're currently
            # not aware of a use-case for a different one than in the paper
            return 1 - np.abs(sampled.eval()) ** 2

        if _is_gradient_supported(ansatz) and self.use_parameter_shift:

            def evaluate_gradient(displacement: np.ndarray) -> np.ndarray:
                """Evaluate the gradient with the parameter-shift rule.

                This is hardcoded here since the gradient framework does not support computing
                gradients for overlaps.

                Args:
                    displacement: The parameters for the ansatz.

                Returns:
                    The gradient.
                """
                # construct lists where each element is shifted by plus (or minus) pi/2
                dim = displacement.size
                plus_shifts = (displacement + np.pi / 2 * np.identity(dim)).tolist()
                minus_shifts = (displacement - np.pi / 2 * np.identity(dim)).tolist()

                evaluated = evaluate_loss(plus_shifts + minus_shifts)

                gradient = (evaluated[:dim] - evaluated[dim:]) / 2

                return gradient

        else:
            evaluate_gradient = None

        return evaluate_loss, evaluate_gradient