コード例 #1
0
    def test_qsve_norm(self):
        """Tests correctness for computing the norm."""
        # Matrix to perform QSVE on
        matrix = np.array([[1, 0], [0, 1]], dtype=np.float64)

        # Create a QSVE object
        qsve = QSVE(matrix)

        # Make sure the Froebenius norm is correct
        self.assertTrue(np.isclose(qsve.matrix_norm(), np.sqrt(2)))
コード例 #2
0
    def test_norm_random(self):
        """Tests correctness for computing the norm on random matrices."""
        for _ in range(100):
            # Matrix to perform QSVE on
            matrix = np.random.rand(4, 4)
            matrix += matrix.conj().T

            # Create a QSVE object
            qsve = QSVE(matrix)

            # Make sure the Froebenius norm is correct
            correct = np.linalg.norm(matrix)
            self.assertTrue(np.isclose(qsve.matrix_norm(), correct))
コード例 #3
0
class LinearSystemSolverQSVE:
    """Quantum algorithm for solving linear systems of equations based on quantum singular value estimation (QSVE)."""
    def __init__(self, Amatrix, bvector, precision=3, cval=0.5):
        """Initializes a LinearSystemSolver.

        Args:
            Amatrix : numpy.ndarray
                Matrix in the linear system Ax = b.

            bvector : numpy.ndarray
                Vector in the linear system Ax = b.

            precision : int
                Number of bits of precision to use in the QSVE subroutine.
        """
        self._matrix = deepcopy(Amatrix)
        self._vector = deepcopy(bvector)
        self._precision = precision
        self._cval = cval
        self._qsve = QSVE(Amatrix,
                          singular_vector=bvector,
                          nprecision_bits=precision)

    @property
    def matrix(self):
        return self._matrix

    @property
    def vector(self):
        return self._vector

    def classical_solution(self, normalized=True):
        """Returns the solution of the linear system found classically.

        Args:
            normalized : bool (default value = True)
                If True, the classical solution is normalized (by the L2 norm), else it is un-normalized.
        """
        xclassical = np.linalg.solve(self._matrix, self._vector)
        if normalized:
            return xclassical / np.linalg.norm(xclassical, ord=2)
        return xclassical

    def _hhl_rotation(self,
                      circuit,
                      eval_register,
                      ancilla_qubit,
                      constant=0.5):
        """Adds the gates for the HHL rotation to perform the transformation


            sum_j beta_j |lambda_j>  ---->  sum_j beta_j / lambda_j |lambda_j>

        Args:

        """
        # The number of controls is the number of qubits in the eval_register
        ncontrols = len(eval_register)

        for ii in range(2**ncontrols):
            # Get the bitstring for this index
            bitstring = np.binary_repr(ii, ncontrols)

            # Do the initial sequence of NOT gates to get controls/anti-controls correct
            for (ind, bit) in enumerate(bitstring):
                if bit == "0":
                    circuit.x(eval_register[ind])

            # Determine the theta value in this amplitude
            theta = self._qsve.binary_decimal_to_float(bitstring)

            # Compute the eigenvalue in this register
            eigenvalue = self._qsve.matrix_norm() * np.cos(np.pi * theta)

            # TODO: Is this correct to do?
            if np.isclose(eigenvalue, 0.0):
                continue

            # Determine the angle of rotation for the Y-rotation
            angle = 2 * np.arccos(constant / eigenvalue)

            # Do the controlled Y-rotation
            mcry(circuit,
                 angle,
                 eval_register,
                 ancilla_qubit,
                 None,
                 mode="noancilla")

            # Do the final sequence of NOT gates to get controls/anti-controls correct
            for (ind, bit) in enumerate(bitstring):
                if bit == "0":
                    circuit.x(eval_register[ind])

    def create_circuit(self, return_registers=False):
        """Creates the circuit that solves the linear system Ax = b."""
        # Get the QSVE circuit
        circuit, qpe_register, row_register, col_register = self._qsve.create_circuit(
            return_registers=True)

        # Make a copy to take the inverse of later
        qsve_circuit = deepcopy(circuit)

        # Add the ancilla register (of one qubit) for the HHL rotation
        ancilla = QuantumRegister(1, name="anc")
        circuit.add_register(ancilla)

        # Do the HHL rotation
        self._hhl_rotation(circuit, qpe_register, ancilla[0], self._cval)

        # Add the inverse QSVE circuit (without the initial data loading subroutines)
        circuit += self._qsve.create_circuit(initial_loads=False).inverse()

        if return_registers:
            return circuit, qpe_register, row_register, col_register, ancilla
        return circuit

    def _run(self, simulator, shots):
        """Runs the quantum circuit and returns the measurement counts."""
        pass

    def quantum_solution(self):
        pass

    def compute_expectation(self, observable):
        pass