From 93eb916d56e29cf306eccd4c8eea4b9f41d539da Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 13:32:25 +0200 Subject: [PATCH 01/25] started linting --- vqls_prototype/hadamard_test.py | 119 +++++---- vqls_prototype/matrix_decomposition.py | 44 ++-- vqls_prototype/variational_linear_solver.py | 1 - vqls_prototype/vqls.py | 254 +++++++++++--------- 4 files changed, 224 insertions(+), 194 deletions(-) diff --git a/vqls_prototype/hadamard_test.py b/vqls_prototype/hadamard_test.py index 4ab67ae..b9646a1 100644 --- a/vqls_prototype/hadamard_test.py +++ b/vqls_prototype/hadamard_test.py @@ -5,11 +5,12 @@ from qiskit.algorithms.exceptions import AlgorithmError from qiskit.opflow import TensoredOp from qiskit.quantum_info import SparsePauliOp -import numpy as np +import numpy as np + class HadammardTest: - r"""Class to compute the Hadamard Test - """ + r"""Class to compute the Hadamard Test""" + def __init__( self, operators: Union[QuantumCircuit, List[QuantumCircuit]], @@ -17,7 +18,7 @@ def __init__( apply_control_to_operator: Optional[Union[bool, List[bool]]] = True, apply_initial_state: Optional[QuantumCircuit] = None, apply_measurement: Optional[bool] = False, - ) : + ): r"""Create the quantum circuits required to compute the hadamard test: .. math:: @@ -37,7 +38,7 @@ def __init__( operators = [operators] if not isinstance(apply_control_to_operator, list): - apply_control_to_operator = [apply_control_to_operator]*len(operators) + apply_control_to_operator = [apply_control_to_operator] * len(operators) if apply_control_to_operator[0]: self.num_qubits = operators[0].num_qubits + 1 @@ -95,21 +96,16 @@ def _build_circuit( Returns: List[QuantumCircuit]: List of quamtum circuits required to compute the Hadammard Test. """ - circuits = [] for imaginary in [False, True]: - if apply_measurement: qc = QuantumCircuit(self.num_qubits, self.num_clbits) else: qc = QuantumCircuit(self.num_qubits) if apply_initial_state is not None: - qc.append( - apply_initial_state, - list(range(1, self.num_qubits)) - ) + qc.append(apply_initial_state, list(range(1, self.num_qubits))) if use_barrier: qc.barrier() @@ -127,10 +123,7 @@ def _build_circuit( # matrix circuit for op, ctrl in zip(operators, apply_control_to_operator): if ctrl: - qc.append( - op.control(1), - list(range(0, self.num_qubits)) - ) + qc.append(op.control(1), list(range(0, self.num_qubits))) else: qc.append(op, list(range(0, self.num_qubits))) if use_barrier: @@ -155,39 +148,43 @@ def _build_observable(self) -> List[TensoredOp]: """ p0 = "I" * self.num_qubits - p1 = "I" * (self.num_qubits-1) + "Z" - one_op_ctrl = SparsePauliOp([p0,p1], np.array([0.5 +0.0j, -0.5 +0.0j])) + p1 = "I" * (self.num_qubits - 1) + "Z" + one_op_ctrl = SparsePauliOp([p0, p1], np.array([0.5 + 0.0j, -0.5 + 0.0j])) return one_op_ctrl def get_value(self, estimator, parameter_sets: List) -> List: - def post_processing(estimator_result) -> List: return [1.0 - 2.0 * val for val in estimator_result.values] ncircuits = len(self.circuits) try: - job = estimator.run(self.circuits, [self.observable]*ncircuits, [parameter_sets]*ncircuits) + job = estimator.run( + self.circuits, + [self.observable] * ncircuits, + [parameter_sets] * ncircuits, + ) results = post_processing(job.result()) except Exception as exc: - raise AlgorithmError("The primitive to evaluate the Hadammard Test failed!") from exc - results = np.array(results).astype('complex128') + raise AlgorithmError( + "The primitive to evaluate the Hadammard Test failed!" + ) from exc + results = np.array(results).astype("complex128") results *= np.array([1.0, 1.0j]) return results.sum() - class HadammardOverlapTest: - r"""Class to compute the Hadamard Test - """ + r"""Class to compute the Hadamard Test""" + def __init__( self, operators: List[QuantumCircuit], use_barrier: Optional[bool] = False, apply_initial_state: Optional[QuantumCircuit] = None, apply_measurement: Optional[bool] = True, - ) : + ): r"""Create the quantum circuits required to compute the hadamard test: .. math:: @@ -204,15 +201,14 @@ def __init__( List[QuantumCircuit]: List of quamtum circuits required to compute the Hadammard Test. """ - self.operator_num_qubits = operators[0].num_qubits - self.num_qubits = 2*operators[0].num_qubits + 1 + self.operator_num_qubits = operators[0].num_qubits + self.num_qubits = 2 * operators[0].num_qubits + 1 if apply_initial_state is not None: if apply_initial_state.num_qubits != operators[0].num_qubits: raise ValueError( "The operator and the initial state circuits have different numbers of qubits" ) - # classical bit for explicit measurement self.num_clbits = self.num_qubits @@ -256,10 +252,9 @@ def _build_circuit( U, Al, Am = operators for imaginary in [False, True]: - - qctrl = QuantumRegister(1, 'qctrl') - qreg0 = QuantumRegister(Al.num_qubits, 'qr0') - qreg1 = QuantumRegister(Am.num_qubits, 'qr1') + qctrl = QuantumRegister(1, "qctrl") + qreg0 = QuantumRegister(Al.num_qubits, "qr0") + qreg1 = QuantumRegister(Am.num_qubits, "qr1") qc = QuantumCircuit(qctrl, qreg0, qreg1) # hadadmard gate on ctrl qbit @@ -267,9 +262,7 @@ def _build_circuit( # prepare psi on the first register if apply_initial_state is not None: - qc.append( - apply_initial_state, qreg0 - ) + qc.append(apply_initial_state, qreg0) # apply U on the second register qc.append(U, qreg1) @@ -278,11 +271,11 @@ def _build_circuit( qc.barrier() # apply Al on the first qreg - idx = [0] + list(range(1,Al.num_qubits+1)) + idx = [0] + list(range(1, Al.num_qubits + 1)) qc.append(Al.control(1), idx) # apply Am^\dagger on the second reg - idx = [0] + list(range(Al.num_qubits+1,2*Al.num_qubits+1)) + idx = [0] + list(range(Al.num_qubits + 1, 2 * Al.num_qubits + 1)) qc.append(Am.inverse().control(1), idx) if use_barrier: @@ -290,11 +283,11 @@ def _build_circuit( # apply the cnot gate for q0, q1 in zip(qreg0, qreg1): - qc.cx(q0,q1) - + qc.cx(q0, q1) + # Sdg on ctrl qbit if imaginary: - qc.rz(-np.pi/2, qctrl) + qc.rz(-np.pi / 2, qctrl) if use_barrier: qc.barrier() @@ -302,48 +295,45 @@ def _build_circuit( # hadamard on ctrl circuit qc.h(qctrl) for q0 in qreg0: - qc.h(q0) + qc.h(q0) # measure if apply_measurement: qc.measure_all(inplace=True) - + circuits.append(qc) return circuits def compute_post_processing_coefficients(self): - """Compute the coefficients for the postprocessing - """ + """Compute the coefficients for the postprocessing""" # compute [1,1,1,-1] \otimes n # these are the coefficients if the qubits of register A and B # are ordered as A0 B0 A1 B1 .... AN BN - c0 = np.array([1,1,1,-1]) - coeffs = np.array([1,1,1,-1]) - for _ in range(1,self.operator_num_qubits): + c0 = np.array([1, 1, 1, -1]) + coeffs = np.array([1, 1, 1, -1]) + for _ in range(1, self.operator_num_qubits): coeffs = np.tensordot(coeffs, c0, axes=0).flatten() - # create all the possible bit strings of a single register bit_strings = [] - for i in range(2**(self.operator_num_qubits)): - bit_strings.append( f"{i:b}".zfill(self.operator_num_qubits) ) + for i in range(2 ** (self.operator_num_qubits)): + bit_strings.append(f"{i:b}".zfill(self.operator_num_qubits)) # coeff in the A0 A1 .. AN B0 B1 ... BN reordered_coeffs = np.zeros_like(coeffs) - # Reorder the coefficients from + # Reorder the coefficients from # A0 B0 A1 B1 ... AN BN => A0 A1 .. AN B0 B1 ... BN for bs1 in bit_strings: for bs2 in bit_strings: - idx = int(bs1+bs2, 2) - new_bit_string = ''.join([i+j for i,j in zip(bs1, bs2)]) - idx_ori = int(new_bit_string,2) + idx = int(bs1 + bs2, 2) + new_bit_string = "".join([i + j for i, j in zip(bs1, bs2)]) + idx_ori = int(new_bit_string, 2) reordered_coeffs[idx] = coeffs[idx_ori] - return reordered_coeffs - + return reordered_coeffs def get_value(self, sampler, parameter_sets: List) -> float: """Compute and return the value of Hadmard overlap test @@ -365,16 +355,17 @@ def post_processing(sampler_result) -> List: Returns: List: value of the overlap hadammard test """ - + quasi_dist = sampler_result.quasi_dists output = [] for qd in quasi_dist: - - # add missing keys - val = np.array([qd[k] if k in qd else 0 for k in range(2**self.num_qubits)]) + # add missing keys + val = np.array( + [qd[k] if k in qd else 0 for k in range(2**self.num_qubits)] + ) # val = (val * val.conj()) - + # v0, v1 = np.array_split(val, 2) v0, v1 = val[0::2], val[1::2] p0 = (v0 * self.post_process_coeffs).sum() @@ -385,10 +376,10 @@ def post_processing(sampler_result) -> List: return output ncircuits = len(self.circuits) - job = sampler.run(self.circuits, [parameter_sets]*ncircuits) + job = sampler.run(self.circuits, [parameter_sets] * ncircuits) results = post_processing(job.result()) - results = np.array(results).astype('complex128') + results = np.array(results).astype("complex128") results *= np.array([1.0, 1.0j]) - return results.sum() \ No newline at end of file + return results.sum() diff --git a/vqls_prototype/matrix_decomposition.py b/vqls_prototype/matrix_decomposition.py index 6181132..0f04cda 100644 --- a/vqls_prototype/matrix_decomposition.py +++ b/vqls_prototype/matrix_decomposition.py @@ -14,9 +14,9 @@ complex_t = TypeVar("complex_t", float, complex) complex_arr_t = npt.NDArray[np.cdouble] + class MatrixDecomposition: - """Base class for the decomposition of a matrix in quantum circuits. - """ + """Base class for the decomposition of a matrix in quantum circuits.""" CircuitElement = namedtuple("CircuitElement", ["coeff", "circuit"]) @@ -56,7 +56,7 @@ def __init__( if matrix is not None: # ignore circuits & coefficients self._matrix, self.num_qubits = self._validate_matrix(matrix) self._coefficients, self._matrices, self._circuits = self.decompose_matrix() - + elif circuits is not None: self._circuits: List[QuantumCircuit] = ( circuits if isinstance(circuits, (list, tuple)) else [circuits] @@ -127,12 +127,10 @@ def _validate_matrix(cls, matrix: complex_arr_t) -> Tuple[complex_arr_t, int]: raise ValueError( f"Input matrix dimension is not a power of 2: {num_qubits}" ) - if not np.allclose(matrix, matrix.conj().T): + if not np.allclose(matrix, matrix.conj().T): raise ValueError(f"Input matrix isn't symmetric:\n{matrix}") - - return matrix, num_qubits - + return matrix, num_qubits @property def matrix(self) -> np.ndarray: @@ -182,7 +180,9 @@ def recompose(self) -> complex_arr_t: coeffs, matrices = self.coefficients, self.matrices return (coeffs.reshape(len(coeffs), 1, 1) * matrices).sum(axis=0) - def decompose_matrix(self) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + def decompose_matrix( + self, + ) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: raise NotImplementedError(f"can't decompose in {self.__class__.__name__!r}") @@ -193,7 +193,9 @@ class SymmetricDecomposition(MatrixDecomposition): math.sx answer: https://math.stackexchange.com/a/1710390 """ - def _create_circuits(self, unimatrices: List[np.ndarray], names: List[str]) -> List[QuantumCircuit]: + def _create_circuits( + self, unimatrices: List[np.ndarray], names: List[str] + ) -> List[QuantumCircuit]: """Construct the quantum circuits from unitary matrices Args: @@ -211,9 +213,10 @@ def make_qc(mat: complex_arr_t, name: str) -> QuantumCircuit: return [make_qc(mat, name) for mat, name in zip(unimatrices, names)] - @staticmethod - def auxilliary_matrix(x: Union[npt.NDArray[np.float_], complex_arr_t]) -> complex_arr_t: + def auxilliary_matrix( + x: Union[npt.NDArray[np.float_], complex_arr_t] + ) -> complex_arr_t: """Returns the auxiliary matrix for the decomposition of size n and derfined as defined as : i * sqrt(I - x^2) Args: @@ -234,7 +237,7 @@ def decompose_matrix( Returns: Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: A tuple containing the list of coefficients numpy matrices, and quantum circuits of the decomposition. """ - + # Normalize norm = np.linalg.norm(self._matrix) mat = self._matrix / norm @@ -259,7 +262,7 @@ def decompose_matrix( unit_coeffs = np.array(unitary_coefficients, dtype=np.cdouble) # create the circuits - names = ['A+','A-'] + names = ["A+", "A-"] circuits = self._create_circuits(unitary_matrices, names) return unit_coeffs, unitary_matrices, circuits @@ -278,20 +281,24 @@ def _create_circuit(pauli_string: str) -> QuantumCircuit: pauli_string (str): the input pauli string Returns: - QuantumCircuit: quantum circuit for the string + QuantumCircuit: quantum circuit for the string """ num_qubit = len(pauli_string) - qc = QuantumCircuit(num_qubit,name=pauli_string) + qc = QuantumCircuit(num_qubit, name=pauli_string) for iqbit, gate in enumerate(pauli_string[::-1]): - if gate.upper()!='I': # identity gate cannot be controlled by ancillary qubit + if ( + gate.upper() != "I" + ): # identity gate cannot be controlled by ancillary qubit qc.__getattribute__(gate.lower())(iqbit) return qc - def decompose_matrix(self) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + def decompose_matrix( + self, + ) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: """Decompose a generic numpy matrix into a sum of Pauli strings. Returns: - Tuple[complex_arr_t, List[complex_arr_t]]: + Tuple[complex_arr_t, List[complex_arr_t]]: A tuple containing the list of coefficients and the numpy matrix of the decomposition. """ @@ -299,7 +306,6 @@ def decompose_matrix(self) -> Tuple[complex_arr_t, List[complex_arr_t], List[Qua unit_mats, coeffs, circuits = [], [], [] for pauli_gates in product(self.basis, repeat=self.num_qubits): - pauli_string = "".join(pauli_gates) pauli_op = Pauli(pauli_string) pauli_matrix = pauli_op.to_matrix() diff --git a/vqls_prototype/variational_linear_solver.py b/vqls_prototype/variational_linear_solver.py index 05feb7b..0d6ae8c 100644 --- a/vqls_prototype/variational_linear_solver.py +++ b/vqls_prototype/variational_linear_solver.py @@ -20,7 +20,6 @@ from qiskit.algorithms.variational_algorithm import VariationalResult - class VariationalLinearSolverResult(VariationalResult): """A base class for linear systems results using variational methods diff --git a/vqls_prototype/vqls.py b/vqls_prototype/vqls.py index 27fb33b..b7321ca 100644 --- a/vqls_prototype/vqls.py +++ b/vqls_prototype/vqls.py @@ -17,26 +17,38 @@ from qiskit.primitives import BaseEstimator, BaseSampler from qiskit.algorithms.variational_algorithm import VariationalAlgorithm from qiskit.utils.validation import validate_min -from qiskit.algorithms.minimum_eigen_solvers.vqe import _validate_bounds,_validate_initial_point +from qiskit.algorithms.minimum_eigen_solvers.vqe import ( + _validate_bounds, + _validate_initial_point, +) from qiskit.circuit.library.n_local.real_amplitudes import RealAmplitudes from qiskit.algorithms.optimizers import Minimizer, Optimizer from qiskit.opflow.gradients import GradientBase -from .variational_linear_solver import VariationalLinearSolver, VariationalLinearSolverResult -from .matrix_decomposition import SymmetricDecomposition, MatrixDecomposition, PauliDecomposition +from .variational_linear_solver import ( + VariationalLinearSolver, + VariationalLinearSolverResult, +) +from .matrix_decomposition import ( + SymmetricDecomposition, + MatrixDecomposition, + PauliDecomposition, +) from .hadamard_test import HadammardTest, HadammardOverlapTest @dataclass class VQLSLog: values: List - parameters: List + parameters: List + def update(self, count, cost, parameters): self.values.append(cost) self.parameters.append(parameters) print(f"VQLS Iteration {count} Cost {cost}", end="\r", flush=True) + class VQLS(VariationalAlgorithm, VariationalLinearSolver): r"""Systems of linear equations arise naturally in many real-life applications in a wide range of areas, such as in the solution of Partial Differential Equations, the calibration of @@ -75,10 +87,10 @@ class VQLS(VariationalAlgorithm, VariationalLinearSolver): # define backend backend = BasicAer.get_backend("statevector_simulator") - + # define an estimator primitive estimator = Estimator() - + # define the logger log = VQLSLog([],[]) @@ -90,7 +102,7 @@ class VQLS(VariationalAlgorithm, VariationalLinearSolver): callback=log.update ) - # solve + # solve res = vqls.solve(A, b, opt) vqls_solution = np.real(Statevector(res.state).data) @@ -99,7 +111,7 @@ class VQLS(VariationalAlgorithm, VariationalLinearSolver): plt.plot([-1, 1], [-1, 1], "--") plt.show() - # plot cost function + # plot cost function plt.plot(log.values) plt.ylabel('Cost Function') plt.xlabel('Iterations') @@ -114,19 +126,18 @@ class VQLS(VariationalAlgorithm, VariationalLinearSolver): def __init__( self, - estimator: BaseEstimator, + estimator: BaseEstimator, ansatz: QuantumCircuit, - optimizer: Union[Optimizer,Minimizer], + optimizer: Union[Optimizer, Minimizer], sampler: Optional[Union[BaseSampler, None]] = None, initial_point: Optional[np.ndarray] = None, gradient: Optional[Union[GradientBase, Callable]] = None, max_evals_grouped: Optional[int] = 1, callback: Optional[Callable[[int, np.ndarray, float, float], None]] = None, - ) -> None: r""" Args: - estimator: an Estimator primitive to compute the expected values of the + estimator: an Estimator primitive to compute the expected values of the quantum circuits needed for the cost function ansatz: A parameterized circuit used as Ansatz for the wave function. optimizer: A classical optimizer. Can either be a Qiskit optimizer or a callable @@ -155,7 +166,7 @@ def __init__( self._num_qubits = None self._max_evals_grouped = max_evals_grouped - + self.estimator = estimator self.sampler = sampler self.ansatz = ansatz @@ -175,9 +186,11 @@ def __init__( self.vector_circuit = None self.matrix_circuits = None - self.default_solve_options = {"use_overlap_test": False, - "use_local_cost_function": False, - "matrix_decomposition": "symmetric"} + self.default_solve_options = { + "use_overlap_test": False, + "use_local_cost_function": False, + "matrix_decomposition": "symmetric", + } @property def num_qubits(self) -> int: @@ -282,7 +295,7 @@ def construct_circuit( Args: matrix (Union[np.ndarray, QuantumCircuit, List]): matrix of the linear system vector (Union[np.ndarray, QuantumCircuit]): rhs of thge linear system - options (Dict): Options to compute define the quantum circuits that compute the cost function + options (Dict): Options to compute define the quantum circuits that compute the cost function Raises: ValueError: if vector and matrix have different size @@ -299,13 +312,12 @@ def construct_circuit( self.vector_circuit = vector elif isinstance(vector, np.ndarray): - # ensure the vector is double vector = vector.astype("float64") # create the circuit nb = int(np.log2(len(vector))) - self.vector_circuit = QuantumCircuit(nb, name='Ub') + self.vector_circuit = QuantumCircuit(nb, name="Ub") # prep the vector if its norm is non nul vec_norm = np.linalg.norm(vector) @@ -314,7 +326,6 @@ def construct_circuit( # general numpy matrix if isinstance(matrix, np.ndarray): - # ensure the matrix is double matrix = matrix.astype("float64") @@ -326,8 +337,10 @@ def construct_circuit( + ". Matrix dimension: " + str(matrix.shape[0]) ) - decomposition = {"pauli": PauliDecomposition, - "symmetric": SymmetricDecomposition} [options["matrix_decomposition"]] + decomposition = { + "pauli": PauliDecomposition, + "symmetric": SymmetricDecomposition, + }[options["matrix_decomposition"]] self.matrix_circuits = decomposition(matrix=matrix) # a single circuit @@ -352,13 +365,13 @@ def construct_circuit( # create only the circuit for = <0|V A_n ^* A_m V|0> # with n != m as the diagonal terms (n==m) always give a proba of 1.0 hdmr_tests_norm = self._get_norm_circuits() - - # create the circuits for + + # create the circuits for # local cost function if options["use_local_cost_function"]: hdmr_tests_overlap = self._get_local_circuits() - # global cost function + # global cost function else: hdmr_tests_overlap = self._get_global_circuits(options) @@ -378,10 +391,11 @@ def _get_norm_circuits(self) -> List[QuantumCircuit]: for jj in range(ii + 1, len(self.matrix_circuits)): mj = self.matrix_circuits[jj] - hdmr_tests_norm.append( HadammardTest( - operators=[mi.circuit.inverse(), mj.circuit], - apply_initial_state=self._ansatz, - apply_measurement=False + hdmr_tests_norm.append( + HadammardTest( + operators=[mi.circuit.inverse(), mj.circuit], + apply_initial_state=self._ansatz, + apply_measurement=False, ) ) return hdmr_tests_norm @@ -404,27 +418,28 @@ def _get_local_circuits(self) -> List[QuantumCircuit]: mj = self.matrix_circuits[jj] for iq in range(num_z): - # circuit for the CZ operation on the iqth qubit - qc_z = QuantumCircuit(num_z+1) - qc_z.cz(0, iq+1) + qc_z = QuantumCircuit(num_z + 1) + qc_z.cz(0, iq + 1) # create Hadammard circuit - hdmr_tests_overlap.append(HadammardTest( - operators = [mi.circuit, - self.vector_circuit.inverse(), - qc_z, - self.vector_circuit, - mj.circuit.inverse()], - apply_control_to_operator=[True, True, False, True, True], - apply_initial_state = self.ansatz, - apply_measurement = False + hdmr_tests_overlap.append( + HadammardTest( + operators=[ + mi.circuit, + self.vector_circuit.inverse(), + qc_z, + self.vector_circuit, + mj.circuit.inverse(), + ], + apply_control_to_operator=[True, True, False, True, True], + apply_initial_state=self.ansatz, + apply_measurement=False, ) ) return hdmr_tests_overlap - def _get_global_circuits(self, - options: dict) -> List[QuantumCircuit]: + def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: """construct circuits needed for the global cost function Args: @@ -438,25 +453,29 @@ def _get_global_circuits(self, # create the circuits for <0|U^* A_l V|0\rangle\langle 0| V^* Am^* U|0> # either using overal test or hadammard test if options["use_overlap_test"]: - for ii in range(len(self.matrix_circuits)): mi = self.matrix_circuits[ii] for jj in range(ii, len(self.matrix_circuits)): mj = self.matrix_circuits[jj] - hdmr_tests_overlap.append(HadammardOverlapTest( - operators = [self.vector_circuit, mi.circuit, mj.circuit], - apply_initial_state = self.ansatz, - apply_measurement = True + hdmr_tests_overlap.append( + HadammardOverlapTest( + operators=[self.vector_circuit, mi.circuit, mj.circuit], + apply_initial_state=self.ansatz, + apply_measurement=True, ) ) else: - for mi in self.matrix_circuits: - hdmr_tests_overlap.append(HadammardTest( - operators=[self.ansatz, mi.circuit, self.vector_circuit.inverse()], - apply_measurement=False, + hdmr_tests_overlap.append( + HadammardTest( + operators=[ + self.ansatz, + mi.circuit, + self.vector_circuit.inverse(), + ], + apply_measurement=False, ) ) @@ -469,14 +488,14 @@ def get_coefficient_matrix(coeffs) -> np.ndarray: Args: coeffs (np.ndarray): list of complex coefficients """ - return coeffs[:,None].conj() @ coeffs[None,:] + return coeffs[:, None].conj() @ coeffs[None, :] def _assemble_cost_function( - self, + self, hdmr_values_norm: np.ndarray, hdmr_values_overlap: np.ndarray, coefficient_matrix: np.ndarray, - options: Dict + options: Dict, ) -> float: """Computes the value of the cost function @@ -491,19 +510,17 @@ def _assemble_cost_function( """ # compute all the terms in <\phi|\phi> = \sum c_i* cj <0|V Ai* Aj V|0> - norm = self._compute_normalization_term( - coefficient_matrix, hdmr_values_norm - ) + norm = self._compute_normalization_term(coefficient_matrix, hdmr_values_norm) if options["use_local_cost_function"]: - # compute all terms in + # compute all terms in # \sum c_i* c_j 1/n \sum_n <0|V* Ai U Zn U* Aj* V|0> sum_terms = self._compute_local_terms( coefficient_matrix, hdmr_values_overlap, norm ) else: - # compute all the terms in + # compute all the terms in # ||^2 = \sum c_i* cj <0|U* Ai V|0><0|V* Aj* U|0> sum_terms = self._compute_global_terms( coefficient_matrix, hdmr_values_overlap, options @@ -513,7 +530,7 @@ def _assemble_cost_function( cost = 1.0 - np.real(sum_terms / norm) # print("Cost function %f" % cost) - return cost + return cost def _compute_normalization_term( self, @@ -552,10 +569,7 @@ def _compute_normalization_term( return out def _compute_global_terms( - self, - coeff_matrix: np.ndarray, - hdmr_values: np.ndarray, - options: Dict + self, coeff_matrix: np.ndarray, hdmr_values: np.ndarray, options: Dict ) -> float: """Compute ||^2 @@ -572,22 +586,23 @@ def _compute_global_terms( """ if options["use_overlap_test"]: - # hdmr_values here contains the values of <0|V* Ai* U|0><0|V Aj U|0> for j>=i # we first insert these values in a tri up matrix size = len(self.matrix_circuits) - hdmr_matrix = np.zeros((size,size)).astype('complex128') + hdmr_matrix = np.zeros((size, size)).astype("complex128") hdmr_matrix[np.tril_indices(size)] = hdmr_values # add the conj that correspond to the tri low part of the matrix # warning the diagonal is also contained in out and we only # want to add the conj of the tri up excluding the diag - hdmr_matrix[np.triu_indices_from(hdmr_matrix, k=1)] = hdmr_matrix[np.tril_indices_from(hdmr_matrix, k=-1)].conj() + hdmr_matrix[np.triu_indices_from(hdmr_matrix, k=1)] = hdmr_matrix[ + np.tril_indices_from(hdmr_matrix, k=-1) + ].conj() # multiply by the coefficent matrix and sum the values out_matrix = coeff_matrix * hdmr_matrix - out = out_matrix.sum() - + out = out_matrix.sum() + else: # hdmr_values here contains the values of <0|V* Ai* U|0> # compute the matrix of the <0|V* Ai* U|0> <0|V Aj U*|0> values @@ -597,10 +612,7 @@ def _compute_global_terms( return out def _compute_local_terms( - self, - coeff_matrix: np.ndarray, - hdmr_values: np.ndarray, - norm: float + self, coeff_matrix: np.ndarray, hdmr_values: np.ndarray, norm: float ) -> float: """Compute the term of the local cost function given by @@ -615,7 +627,7 @@ def _compute_local_terms( Returns: float: value of the sum """ - + # add all the hadamard test values corresponding to the insertion of Z gates on the same cicuit # b_ij = \sum_n \\frac{1}{n} \\sum_n \\langle 0|V^* A_i U Z_n U^* A_j^* V|0\\rangle num_zgate = self.matrix_circuits[0].circuit.num_qubits @@ -624,15 +636,16 @@ def _compute_local_terms( # hdmr_values then contains the values of <0|V* Ai* U|0><0|V Aj U|0> for j>=i # we first insert these values in a tri up matrix size = len(self.matrix_circuits) - hdmr_matrix = np.zeros((size,size)).astype('complex128') + hdmr_matrix = np.zeros((size, size)).astype("complex128") hdmr_matrix[np.triu_indices(size)] = hdmr_values # add the conj that correspond to the tri low part of the matrix # warning the diagonal is also contained in out and we only - # want to add the conj of the tri up excluding the diag - hdmr_matrix[np.tril_indices_from(hdmr_matrix, k=-1)] = hdmr_matrix[np.triu_indices_from(hdmr_matrix, k=1)].conj() + # want to add the conj of the tri up excluding the diag + hdmr_matrix[np.tril_indices_from(hdmr_matrix, k=-1)] = hdmr_matrix[ + np.triu_indices_from(hdmr_matrix, k=1) + ].conj() - # multiply by the coefficent matrix and sum the values out_matrix = coeff_matrix * hdmr_matrix out = (out_matrix).sum() @@ -647,10 +660,10 @@ def _compute_local_terms( def get_cost_evaluation_function( self, - hdmr_tests_norm: List, + hdmr_tests_norm: List, hdmr_tests_overlap: List, coefficient_matrix: np.ndarray, - options: Dict + options: Dict, ) -> Callable[[np.ndarray], Union[float, List[float]]]: """Generate the cost function of the minimazation process @@ -672,24 +685,31 @@ def get_cost_evaluation_function( raise RuntimeError( "The ansatz must be parameterized, but has 0 free parameters." ) - - def cost_evaluation(parameters): + def cost_evaluation(parameters): # estimate the expected values of the norm circuits - hdmr_values_norm = np.array([hdrm.get_value(self.estimator, parameters) - for hdrm in hdmr_tests_norm]) + hdmr_values_norm = np.array( + [hdrm.get_value(self.estimator, parameters) for hdrm in hdmr_tests_norm] + ) if options["use_overlap_test"]: - hdmr_values_overlap = np.array([hdrm.get_value(self.sampler, parameters) - for hdrm in hdmr_tests_overlap]) + hdmr_values_overlap = np.array( + [ + hdrm.get_value(self.sampler, parameters) + for hdrm in hdmr_tests_overlap + ] + ) else: - hdmr_values_overlap = np.array([hdrm.get_value(self.estimator, parameters) - for hdrm in hdmr_tests_overlap]) + hdmr_values_overlap = np.array( + [ + hdrm.get_value(self.estimator, parameters) + for hdrm in hdmr_tests_overlap + ] + ) # compute the total cost - cost = self._assemble_cost_function(hdmr_values_norm, - hdmr_values_overlap, - coefficient_matrix, - options) + cost = self._assemble_cost_function( + hdmr_values_norm, hdmr_values_overlap, coefficient_matrix, options + ) # get the intermediate results if required if self._callback is not None: @@ -697,13 +717,16 @@ def cost_evaluation(parameters): self._callback(self._eval_count, cost, parameters) else: self._eval_count += 1 - print(f"VQLS Iteration {self._eval_count} Cost {cost}", end="\r", flush=True) + print( + f"VQLS Iteration {self._eval_count} Cost {cost}", + end="\r", + flush=True, + ) return cost return cost_evaluation - def _validate_solve_options(self, options: Union[Dict, None]) -> Dict: """validate the options used for the solve methods @@ -718,22 +741,30 @@ def _validate_solve_options(self, options: Union[Dict, None]) -> Dict: else: for k in options.keys(): if k not in self.default_solve_options.keys(): - raise ValueError("Option {k} not recognized, valid keys are {valid_keys}") + raise ValueError( + "Option {k} not recognized, valid keys are {valid_keys}" + ) for k in self.default_solve_options.keys(): if k not in options.keys(): options[k] = self.default_solve_options[k] - + if options["use_overlap_test"] and options["use_local_cost_function"]: - raise ValueError("Local cost function cannot be used with Hadamard Overlap test") + raise ValueError( + "Local cost function cannot be used with Hadamard Overlap test" + ) if options["use_overlap_test"] and self.sampler is None: - raise ValueError("Please provide a sampler primitives when using Hadamard Overlap test") - + raise ValueError( + "Please provide a sampler primitives when using Hadamard Overlap test" + ) + valid_matrix_decomposition = ["symmetric", "pauli"] if options["matrix_decomposition"].lower() not in valid_matrix_decomposition: - raise ValueError("matrix decomposition {k} not recognized, valid keys are {valid_matrix_decomposition}") + raise ValueError( + "matrix decomposition {k} not recognized, valid keys are {valid_matrix_decomposition}" + ) - return options + return options def solve( self, @@ -746,7 +777,7 @@ def solve( Args: matrix (Union[List, np.ndarray, QuantumCircuit]): matrix of the linear system vector (Union[np.ndarray, QuantumCircuit]): rhs of the linear system - options (Union[Dict, None]): options for the calculation of the cost function + options (Union[Dict, None]): options for the calculation of the cost function Returns: VariationalLinearSolverResult: Result of the optimization and solution vector of the linear system @@ -756,11 +787,14 @@ def solve( options = self._validate_solve_options(options) # compute the circuits needed for the hadamard tests - hdmr_tests_norm, hdmr_tests_overlap = self.construct_circuit(matrix, vector, - options) + hdmr_tests_norm, hdmr_tests_overlap = self.construct_circuit( + matrix, vector, options + ) - # compute he coefficient matrix - coefficient_matrix = self.get_coefficient_matrix(np.array([mi.coeff for mi in self.matrix_circuits])) + # compute he coefficient matrix + coefficient_matrix = self.get_coefficient_matrix( + np.array([mi.coeff for mi in self.matrix_circuits]) + ) # set an expectation for this algorithm run (will be reset to None at the end) initial_point = _validate_initial_point(self.initial_point, self.ansatz) @@ -772,8 +806,9 @@ def solve( self._eval_count = 0 # get the cost evaluation function - cost_evaluation = self.get_cost_evaluation_function(hdmr_tests_norm, hdmr_tests_overlap, - coefficient_matrix, options) + cost_evaluation = self.get_cost_evaluation_function( + hdmr_tests_norm, hdmr_tests_overlap, coefficient_matrix, options + ) if callable(self.optimizer): opt_result = self.optimizer( # pylint: disable=not-callable @@ -796,5 +831,4 @@ def solve( # final ansatz solution.state = self.ansatz.assign_parameters(solution.optimal_parameters) - return solution From 6447692e77f9130e72577c14f59bd1d5d2ea6d45 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 14:04:02 +0200 Subject: [PATCH 02/25] format py files --- docs/tutorials/vqls.ipynb | 48 ++++++++++++++--------------- tests/test_decomposition.py | 6 ++-- tests/test_vqls.py | 60 ++++++++++++++++--------------------- vqls_prototype/__init__.py | 5 ++-- 4 files changed, 55 insertions(+), 64 deletions(-) diff --git a/docs/tutorials/vqls.ipynb b/docs/tutorials/vqls.ipynb index dc1062e..f5b7a8d 100644 --- a/docs/tutorials/vqls.ipynb +++ b/docs/tutorials/vqls.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 8, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -72,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -89,14 +89,14 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/tmp/ipykernel_5891/2242500068.py:2: DeprecationWarning: The NumPyLinearSolver class is deprecated as of Qiskit Terra 0.22.0 and will be removed no sooner than 3 months after the release date. \n", + "/tmp/ipykernel_3781/2242500068.py:2: DeprecationWarning: The NumPyLinearSolver class is deprecated as of Qiskit Terra 0.22.0 and will be removed no sooner than 3 months after the release date. \n", " classical_solution = NumPyLinearSolver().solve(A, b / np.linalg.norm(b))\n" ] } @@ -117,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -134,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -152,19 +152,19 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "VQLS Iteration 232 Cost 2.6877192693675056e-09\n", - " Normal return from subroutine COBYLA\n", + "VQLS Iteration 250 Cost 0.0034253113374054234\n", + " Return from subroutine COBYLA because the MAXFUN limit has been reached.\n", "\n", - " NFVALS = 232 F = 2.687719E-09 MAXCV = 0.000000E+00\n", - " X = 1.013072E+00 -1.615175E+00 1.382864E+00 -2.983881E+00 -2.247086E+00\n", - " -2.141579E-01 1.692587E+00 -2.007386E+00\n" + " NFVALS = 250 F = 3.425311E-03 MAXCV = 0.000000E+00\n", + " X = 2.446648E-01 1.512205E+00 1.530916E+00 -2.035130E+00 -1.203258E+00\n", + " -1.885166E+00 6.996742E-01 -3.191750E+00\n" ] } ], @@ -184,22 +184,22 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[]" + "[]" ] }, - "execution_count": 15, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -221,22 +221,22 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[]" + "[]" ] }, - "execution_count": 16, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGdCAYAAADAAnMpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA2TUlEQVR4nO3de3zU9Z3v8ffMhCQECBdDEi5R0KrUgqBQ0mi9HbOg67J2bfew6imUY/FoYY81tlWsQm27xtqV5ewuLVurtbunKuqq3SqlpdHosUQpt3oDFAQTgYSbJCGQ28z3/JHML7/fLzNJJr+5kMzr+XjkkZn5/X4z3/lJ4d3v5fP1GWOMAAAAUsSf6gYAAID0RhgBAAApRRgBAAApRRgBAAApRRgBAAApRRgBAAApRRgBAAApRRgBAAAplZHqBvRFKBTSgQMHNGLECPl8vlQ3BwAA9IExRo2NjRo/frz8/uj9HwMijBw4cEBFRUWpbgYAAOiHmpoaTZw4MerxARFGRowYIanjy+Tm5qa4NQAAoC8aGhpUVFRk/TsezYAII+GhmdzcXMIIAAADTG9TLJjACgAAUoowAgAAUoowAgAAUoowAgAAUoowAgAAUoowAgAAUirmMPL6669r3rx5Gj9+vHw+n1588cVer6msrNTFF1+srKwsfeYzn9ETTzzRj6YCAIDBKOYw0tTUpOnTp2v16tV9On/v3r267rrrdNVVV2n79u365je/qa9//ev63e9+F3NjAQDA4BNz0bNrr71W1157bZ/PX7NmjSZPnqxHHnlEkvTZz35Wb7zxhv7pn/5Jc+fOjfXjAQDAIJPwOSNVVVUqLS11vDZ37lxVVVVFvaalpUUNDQ2OHwAAMDglPIzU1taqoKDA8VpBQYEaGhp06tSpiNeUl5dr5MiR1g+b5AEAMHidlqtpli1bpvr6euunpqYm1U0CAAAJkvCN8goLC1VXV+d4ra6uTrm5uRo6dGjEa7KyspSVlZXopvXoyIkWPbflE91w8QTlj8hOaVsAABjMEt4zUlJSooqKCsdrGzZsUElJSaI/2pMn36rWQ7/dqf+o+jjVTQEAYFCLOYycOHFC27dv1/bt2yV1LN3dvn27qqurJXUMsSxYsMA6/7bbbtNHH32k73znO9q5c6d+8pOf6JlnntGdd94Zn2+QICda2h2/AQBAYsQcRjZv3qyLLrpIF110kSSprKxMF110kZYvXy5JOnjwoBVMJGny5Ml6+eWXtWHDBk2fPl2PPPKIfv7zn5/2y3pDISNJMibFDQEAYJCLec7IlVdeKdPDv9CRqqteeeWV2rZtW6wflVLhbxgijQAAkFCn5Wqa00E4hBBGAABILMJIFOEMEgylth0AAAx2hJEowj0iPQ1JAQAA7wgjUTBMAwBAchBGouhcTGP9BgAAiUEYicLQMwIAQFIQRqIIhcK/CSMAACQSYSSKrjkjKW4IAACDHGEkiq45I6QRAAASiTAShTGUgwcAIBkII1GwtBcAgOQgjEQRsiqwEkYAAEgkwkgUTGAFACA5CCNRhEdnKAcPAEBiEUZsfv7/PtLv3quVxJwRAACSJSPVDThd1Bw7qR++vEP5I7I093OFDNMAAJAk9Ix0OtUWdPymzggAAMlBGOkUXjXjnitCGAEAILEII53CYcQ9PBPeowYAACQGYaSTe8IqE1gBAEgOwkinrp4ROX6TRQAASCzCSKeuYZnw3JGO30HSCAAACUUY6cQwDQAAqUEY6dRtmKZz4ip1RgAASCzCSKeQLXUYY6weEcrBAwCQWISRTva5ISHTNXGVYRoAABKLMNIpGLKHka6ekSB1RgAASCjCSKeQiRxGGKYBACCx0nqjvI27j+hoU6s+P2mMowckFJLCEYRhGgAAEiute0Z+/Ptd+vuntuntT45H6BkJP05R4wAASBNp3TMS8PkkdYQPewdIx3PqjAAAkAxpHUb8/o4wEgxJRs7VNFbRM7pGAABIqLQOI+GekaCtJ0TqrDNC0TMAAJIivcNIZ89IKGSi94wwTAMAQEKldRjpGqaxRxHnHBKyCAAAiZXWYSTDFkbsQiFDzwgAAEmS1mHEb5sz4rO9bh+mcQcVAAAQX2kdRgKdVVaCISOfLY3Yh2nIIgAAJFaah5GuOiM+V50RysEDAJAcaR1GrGGakHOYxhjZKrASRgAASKS0DiMB2wRWn22cxt4zwjANAACJldZ709jLwdsrrYZM15LeSBVYjTHavO+Yjp5oSUo7AQAYzNI7jHT2jLSHjIK24ZhgL0t73zvQoK+sqdK3n3s7OQ0FAGAQY5hGnRVYbZNGTC/DNIcamx2/AQBA/6V1z4hjozzjLgcfftw9jVj71oQS3kQAAAa99O4ZsRU9U8g5gdVYS3u7Xxce0mFuKwAA3qV3GLEN09j7iDpW03Q8DkZII4YaJAAAxE16D9PYekbsq2ZMhF17/7TvmJ7dXNP5mhzHAABA/6V5z0jH74g9I6GuYRpjjO565s+qPnZSXzj7DGqQAAAQR2keRjoSSHvIOG5EMGQcc0WMkRqa2yRJjc3tVghhmAYAAO/SPIx0/HaXg7fv2tvx3Fi79/Y2uRUAAMQmreeMOCqwOnpCnM+DrmGbngqiAQCA2KR1GPHb9qZx9oQ4g4YxXatqOnpJOl9PXlMBABi00jqM2HtGgiHnsIy906NjQmvH46DpuVQ8AACITVrPGfE7du11hhF3T4lV6Mw2Z4QKrAAAeJfWYcS+UZ7f5xyWcU9gtS/nZTUNAADxk9ZhJMNWgTVoCyMdc0i6zgsGu4ZtQrb5JUQRAAC869eckdWrV2vSpEnKzs5WcXGxNm3a1OP5q1at0vnnn6+hQ4eqqKhId955p5qbU7/jbVcFVmfZd3cJ+DbbeExvm+gBAIDYxBxG1q5dq7KyMq1YsUJbt27V9OnTNXfuXB06dCji+U8++aTuuecerVixQjt27NBjjz2mtWvX6t577/XceK/se9PYy8GHXKVV24Puya1UYAUAIF5iDiMrV67U4sWLtWjRIl1wwQVas2aNcnJy9Pjjj0c8f+PGjbr00kt10003adKkSZozZ45uvPHGXntTksG5tLfr9fZewkjQVnMEAAB4E1MYaW1t1ZYtW1RaWtr1Bn6/SktLVVVVFfGaSy65RFu2bLHCx0cffaR169bpL//yL6N+TktLixoaGhw/iRCwbZTnGKYJ9W2YhgmsAAB4F9ME1iNHjigYDKqgoMDxekFBgXbu3BnxmptuuklHjhzRF7/4RRlj1N7erttuu63HYZry8nI98MADsTStX+wb5dmHZtw9I21BexixD9MQRgAA8CrhRc8qKyv14IMP6ic/+Ym2bt2q559/Xi+//LJ+8IMfRL1m2bJlqq+vt35qamoS0rbwBNb2kLPoWdBVQMQ+TGMMq2kAAIinmHpG8vLyFAgEVFdX53i9rq5OhYWFEa+5//779dWvflVf//rXJUnTpk1TU1OTbr31Vn33u9+V3989D2VlZSkrKyuWpvVLRsC+N01XtGgL9tAzErKtpmEGKwAAnsXUM5KZmamZM2eqoqLCei0UCqmiokIlJSURrzl58mS3wBEIBCSlfs6FtbS3W8+IawKr/Zi9Z4QsAgCAZzEXPSsrK9PChQs1a9YszZ49W6tWrVJTU5MWLVokSVqwYIEmTJig8vJySdK8efO0cuVKXXTRRSouLtbu3bt1//33a968eVYoSZWAbTVNsIfVNPaeEWPbt4Y5IwAAeBdzGJk/f74OHz6s5cuXq7a2VjNmzND69eutSa3V1dWOnpD77rtPPp9P9913n/bv36+xY8dq3rx5+od/+If4fYt+sm+UZ++lCQadc0baHEt7u4ZniCIAAHjXr3LwS5cu1dKlSyMeq6ysdH5ARoZWrFihFStW9OejEspeZyTYw2qadtdqmiCraQAAiJuEr6Y5nQX6OGekW8+I6XoMAAC8Se8w4u8qembv5XD3jNjDSShkG9IhjAAA4BlhRFIw5Awc7UH3ahrnME2IYRoAAOKGMKKO3g57/nAXPWttZ9deAAASJa3DiN+2N01P5eDtz0NUYAUAIK7SOow4ekZ6KnoWpc6IMakv3AYAwECX5mGk43dvE1jdq2nsYYUsAgCAN2kdRqyN8oLOMNK9HHzIccx+LvNGAADwJq3DiDVMY9xFz6JXYLUP00jMGwEAwCvCiMK9HV2vu5f2OnbtNaJnBACAOCKMKFLPiHsCa+TVNBJzRgAA8Cq9w0hfy8GHItcZkQgjAAB4ldZhxO8Ypuljz0jIucMvwzQAAHiT1mHE3jPiXE3jnsDq2rU3RBgBACBe0juM2DbKs+WNCBNYI+/aG34OAAD6L63DiN+qwKoe64wEo2yUJ4m1vQAAeJTWYSTD0TPStzkj7jojDNMAAOBNWocRv33OSI+raezHqDMCAEA8pXUYCc8ZkZy9Id0qsLa7h2m6jhFFAADwJr3DiK8rjLQGnfvP2NnDiTHsTQMAQDyldRjx2759T3NGuq2mYddeAADiJq3DiH2Yxq6nnhHKwQMAEF9pHUb8vshhJLY6I6QRAAC8SOswktHHnhF3BVbKwQMAED9pHUaiDdO0uVbTuPemYaM8AADiJ63DiM/nU6SRmp57RsScEQAA4iitw4jkXN4b5p4z0u7aGI85IwAAxE/ahxF/hKGabqtpgs46I8wZAQAgftI+jETsGemhzoh7HxuiCAAA3hBGIvaMuCawhnqaM0IcAQDAC8JIhDDS2669zjkjCWsaAABpgTASKYx0K3pm6xkJiTkjAADEUdqHkUhVWLuXg4++moYsAgCAN2kfRgIR7kC7a86IvWckyK69AADEFWEkQs+Iex5IW9BZ5IyeEQAA4iftw0ikOiM9CRmjUMgZTgAAQP+lfRiJtj9NNO6lvQzTAADgDWGkPz0jlIMHACBuCCORdsrrgbscPFEEAABvCCMx9owEQ4YKrAAAxFHah5FIdUZ6EnKtpqECKwAA3qR9GIm1Z8S464yQRgAA8CTtw0jsS3udAYQoAgCAN2kfRgKxZRFW0wAAEGdpH0Yy/LHdgu4TWOPdIgAA0kvah5EYs4iMcQYQwggAAN6kfRjpX9EzKrACABAvaR9GYl/aSxgBACCe0j6M9G9vmq7nZBEAALwhjMTaMxJyl4MnjQAA4EXah5HY64wYBUP2omfxbhEAAOkl7cNIhsdhGuaMAADgTdqHkVh7Rtzl4IkiAAB4k/ZhJOY5I93qjBBHAADwgjBi6xnpSydJ96W9iWgVAADpI+3DiL3OSEag99tBOXgAAOIr7cOIPX8M6UPXiGECKwAAcdWvMLJ69WpNmjRJ2dnZKi4u1qZNm3o8//jx41qyZInGjRunrKwsnXfeeVq3bl2/Ghxv9mEadwG0SCttQsYoFKICKwAA8ZIR6wVr165VWVmZ1qxZo+LiYq1atUpz587Vrl27lJ+f3+381tZW/cVf/IXy8/P13HPPacKECfr44481atSoeLTfM3sAGeIapgn4fWp3TQpxzxkhiwAA4E3MYWTlypVavHixFi1aJElas2aNXn75ZT3++OO65557up3/+OOP69ixY9q4caOGDBkiSZo0aZK3VseRfTWNO4xk+H1qcZ3vHqahAisAAN7ENEzT2tqqLVu2qLS0tOsN/H6Vlpaqqqoq4jX/9V//pZKSEi1ZskQFBQWaOnWqHnzwQQWDwaif09LSooaGBsdPotjrjGQEXMM0ESa0duspoQIrAACexBRGjhw5omAwqIKCAsfrBQUFqq2tjXjNRx99pOeee07BYFDr1q3T/fffr0ceeUQ//OEPo35OeXm5Ro4caf0UFRXF0syY9NYz4haMMGwDAAD6L+GraUKhkPLz8/Wzn/1MM2fO1Pz58/Xd735Xa9asiXrNsmXLVF9fb/3U1NQkrH32OSPu8BFpR992V1cIUQQAAG9imjOSl5enQCCguro6x+t1dXUqLCyMeM24ceM0ZMgQBQIB67XPfvazqq2tVWtrqzIzM7tdk5WVpaysrFia1m/OYZrYe0aowAoAgDcx9YxkZmZq5syZqqiosF4LhUKqqKhQSUlJxGsuvfRS7d69WyFbj8IHH3ygcePGRQwiyeYcpul9zkhb0D1Mk5h2AQCQLmIepikrK9Ojjz6qX/7yl9qxY4duv/12NTU1WatrFixYoGXLllnn33777Tp27JjuuOMOffDBB3r55Zf14IMPasmSJfH7Fh7EWmekPegcpmHOCAAA3sS8tHf+/Pk6fPiwli9frtraWs2YMUPr16+3JrVWV1fL7+/KOEVFRfrd736nO++8UxdeeKEmTJigO+64Q3fffXf8voUHPdUZibSjr3s1DVkEAABvYg4jkrR06VItXbo04rHKyspur5WUlOjNN9/sz0clnDOM9N4zwpwRAADiK+33pnFslOfvXoHVrXtF1sS0CwCAdJH2YcSxUV4fJrC60TMCAIA3aR9GeuoZiTRM40bPCAAA3qR9GAn0UA4+0jCNG6tpAADwJu3DSEYPq2n60jMCAAC8Sfsw4o+xHLwbPSMAAHiT9mHEXoHVPWHV3VMSCXNGAADwJu3DiL+HOiP0jAAAkHhpH0YCHlfTkEUAAPCGMOKxZ4Q6IwAAeJP2YcTfw9Je6owAAJB4aR9GMvw9DNP0qQJr3JsEAEBaSfsw4qzA2p+eEdIIAABepH0YccwZyeh9ozw35owAAOANYcR2B/rTM0IUAQDAm7QPI/Zhmm7l4PtU9Iw4AgCAF2kfRnraKI/VNAAAJB5hxD5nxB99zki0YELPCAAA3hBGbMM0fr9PtqfOZb+BKL0kZBEAADwhjNgCR8DvnEMSsPWU2EOLHT0jAAB4k/ZhxF6B1e/zyT4aY+8N8fudx8KYMwIAgDdpH0YcwzQ+X9QiaAG/81gYHSMAAHhDGOkhcDiO+SKHEYZpAADwJu3DiL9bz0jXMXvPiN/vkz/C3aICKwAA3qR9GLHPC+nWMxJwTmCN3DOS2PYBADDYpX0YcQ7LyLG0d0hf5oywthcAAE/SPowE3KtpXEMzXY+dQSWMnhEAALwhjPii935k9GECK3NGAADwJu3DiH1Sqntpb8DVSxKIUGiELAIAgDdpH0a6DdM4VtO4J7B2v56lvQAAeEMY6WmYxrXSxsdqGgAA4o4w0m1vmq5jGT30moTRMQIAgDeEEVfg8EWrwBq1HDxpBAAAL9I+jPjdgcN2R+xzRvw+UQ4eAIAESPsw0uNGee5deyPcLeaMAADgDWHE1TMSiLXOSGKbBwDAoJf2YcS9UZ49b7jrjDBMAwBA/KV9GOm+msbeM+KsMxKpHDwTWAEA8Cbtw4h9ua57zoh9jkj01TSJbB0AAINf2ocRn6+rzHtHYbOuYx0BpOOx3zWfJIxhGgAAvEn7MCJ1DdV06xmxPQ/42LUXAIBEyEh1A04H82cV6eNjJzVh1FDXxnnhOSSGomcAACQIYUTSD7401XpsDxw+26RVvy9ynRGyCAAA3jBM4xJ1mIalvQAAJARhxMW5usY2nyRqGElWywAAGJwIIy7RiqAFou3am6R2AQAwWBFGXJxzRrqeuzfKCwcTJrACAOANYcTF5ximcdYZcW6i13HrmDMCAIA3hBGX6HVGXAXROp+QRQAA8IYw4tKtzoitOqt9H5vwjr70jAAA4A1hxMVdZyTaME0gEA4jSW0eAACDDmHExT1JtfdhGtIIAABeEEZcou3i6y56Fh6yIYsAAOANYcSl2wRWv+2xLagwZwQAgPggjLj47GMx9mEavxwTWJkzAgBAfBBGXNzl4K2iZ36fI6hkdHaZkEUAAPCGMOLS13LwXXNGiCMAAHjRrzCyevVqTZo0SdnZ2SouLtamTZv6dN3TTz8tn8+nL33pS/352KSwD8X0NIGVOSMAAMRHzGFk7dq1Kisr04oVK7R161ZNnz5dc+fO1aFDh3q8bt++ffrWt76lyy67rN+NTQbHlBFf1xJeezAJP5ekUCipzQMAYNCJOYysXLlSixcv1qJFi3TBBRdozZo1ysnJ0eOPPx71mmAwqJtvvlkPPPCAzj77bE8NTrRowzQdK2vse9N0DtMktXUAAAw+MYWR1tZWbdmyRaWlpV1v4PertLRUVVVVUa/7/ve/r/z8fN1yyy19+pyWlhY1NDQ4fpIl2gTWgF/MGQEAIAFiCiNHjhxRMBhUQUGB4/WCggLV1tZGvOaNN97QY489pkcffbTPn1NeXq6RI0daP0VFRbE005OodUaYMwIAQEIkdDVNY2OjvvrVr+rRRx9VXl5en69btmyZ6uvrrZ+ampoEttLJvnzX11M5eCqwAgAQFxmxnJyXl6dAIKC6ujrH63V1dSosLOx2/p49e7Rv3z7NmzfPei3UOeMzIyNDu3bt0jnnnNPtuqysLGVlZcXStLgJD8X4fOGN8qKtpunIcfSMAADgTUw9I5mZmZo5c6YqKiqs10KhkCoqKlRSUtLt/ClTpuidd97R9u3brZ+//uu/1lVXXaXt27cndfilr8I9HlaxM9sE1oAtjNAzAgBAfMTUMyJJZWVlWrhwoWbNmqXZs2dr1apVampq0qJFiyRJCxYs0IQJE1ReXq7s7GxNnTrVcf2oUaMkqdvrpwtfhBAidfaM2KKbFUaS2joAAAafmMPI/PnzdfjwYS1fvly1tbWaMWOG1q9fb01qra6ult8/cAu7dg3TuHpIXOXgA0xgBQAgLmIOI5K0dOlSLV26NOKxysrKHq994okn+vORSeMenolWDp7VNAAAxMfA7cJIkEjDMx2/nct+rZ4RKrACAOAJYcSl2/BMlHLwGfZuEgAA0G+EEZdw4AjnjuwhHbdoaGbA1TPC0l4AAOKhX3NGBrNAuOJqZ/BY+t/O1eS8Ybrq/Hxtrz7e7TzCCAAA3hBGXNwTWGcUjdKMolEdr/m794yQRQAA8IZhGhf3nBHnsa7HXatpktIsAAAGLcKIi7vOiF3kCqykEQAAvCCMuLiHaSIdk7p6RogiAAB4QxhxcdcZiXRMkgIBip4BABAPhBEX9940kY5JtjkjTBoBAMATwohLV52RSD0jtjkjPnbtBQAgHggjLladkQh3xjFME17am4Q2AQAwmBFGXHpa2muvM5LBnBEAAOKCMOLi3pMm0jHJtlEeYQQAAE8IIy5WnZEejkm2pb1kEQAAPCGMuLg3yot0TLIXPUtKswAAGLQIIy6+HuqMRC4HTxoBAMALwohLT3NGArZxGj9hBACAuCCMuIQDR2/DNJSDBwAgPggjLn0uBx+uM2LYLA8AAC8IIy5WnZEId8bnmMDa9TpZBACA/iOMuPS9zkjXrSOLAADQf4QRF6vOSMQJrF2Ph9jGbJjECgBA/xFGXPx93LU3QBgBACAuCCMuPdUZiVT0TGLOCAAAXhBGXMIhI1LPiHM1DWEEAIB4IIy4dJWD77lnJMM2gZVhGgAA+o8w4tI1TNP9mN9RgbXrdcIIAAD9RxhxmTg6R5I0YVROt2POXXtZ2gsAQDxkpLoBp5uZZ43W7++8XGeOiRRGbMM0AduckVBSmgYAwKBEGIngvIIREV93TGD1sbQXAIB4YJgmBtHqjBBFAADoP8JIDAIUPQMAIO4IIzGwr6Dx+3zWsA1hBACA/iOMxMA+TOP3dT0niwAA0H+EkRjYV9P4bD0jhBEAAPqPMBID+2oae88IwzQAAPQfYSQG7gms4WeEEQAA+o8wEgPnnBGfNWxDFgEAoP8IIzGwD9P4fGLOCAAAcUAYiYFjozxbzwjDNAAA9B9hJAbOCaw+hSeNEEUAAOg/wkgM/K46I/SMAADgHWEkBtHrjBBGAADoL8JIDPzupb1Wz0iqWgQAwMBHGImBz1X0jNU0AAB4RxiJgXuYhgqsAAB4RxiJQcDv2iiv8zFhBACA/iOMxMC9tJcKrAAAeEcYiUH3cvAdjwkjAAD0H2EkBu5y8MwZAQDAO8JIDLov7e14TBgBAKD/CCMxCETZm4YoAgBA/xFGYhC9zghxBACA/iKMxCB6nZFUtQgAgIGPMBKDcBgJ94j4WE0DAIBnGaluwEAyZlimJowaqrwRWZLYtRcAgHjoV8/I6tWrNWnSJGVnZ6u4uFibNm2Keu6jjz6qyy67TKNHj9bo0aNVWlra4/mns8wMv1751hX6z9tKJFGBFQCAeIg5jKxdu1ZlZWVasWKFtm7dqunTp2vu3Lk6dOhQxPMrKyt144036tVXX1VVVZWKioo0Z84c7d+/33PjUyErI6CMQMdts+aQkEUAAOi3mMPIypUrtXjxYi1atEgXXHCB1qxZo5ycHD3++OMRz//Vr36lb3zjG5oxY4amTJmin//85wqFQqqoqPDc+FTrqjOS2nYAADCQxRRGWltbtWXLFpWWlna9gd+v0tJSVVVV9ek9Tp48qba2No0ZMya2lp6GmDMCAIB3MU1gPXLkiILBoAoKChyvFxQUaOfOnX16j7vvvlvjx493BBq3lpYWtbS0WM8bGhpiaWbSUIEVAADvkrq096GHHtLTTz+tF154QdnZ2VHPKy8v18iRI62foqKiJLay76jACgCAdzGFkby8PAUCAdXV1Tler6urU2FhYY/X/uM//qMeeugh/f73v9eFF17Y47nLli1TfX299VNTUxNLM5OGCqwAAHgXUxjJzMzUzJkzHZNPw5NRS0pKol738MMP6wc/+IHWr1+vWbNm9fo5WVlZys3NdfyclsJzRkIpbgcAAANYzEXPysrKtHDhQs2aNUuzZ8/WqlWr1NTUpEWLFkmSFixYoAkTJqi8vFyS9KMf/UjLly/Xk08+qUmTJqm2tlaSNHz4cA0fPjyOXyX5/KzsBQDAs5jDyPz583X48GEtX75ctbW1mjFjhtavX29Naq2urpbf39Xh8tOf/lStra36yle+4nifFStW6Hvf+5631qcYq2kAAPCuX+Xgly5dqqVLl0Y8VllZ6Xi+b9++/nzEgMCcEQAAvGOjPA98nQXhySIAAPQfYcQDKrACAOAdYcQD5owAAOAdYcQDKrACAOAdYcQDa9deAADQb4QRD+gZAQDAO8KIBz4qsAIA4BlhxAMqsAIA4B1hxANW0wAA4B1hxAMqsAIA4B1hxJNwz0iKmwEAwABGGPGgq2ckte0AAGAgI4x4wJwRAAC8I4x44GPOCAAAnhFGPAj3jBBFAADoP8KIB1YFVmawAgDQb4QRD6wKrGQRAAD6jTDiARVYAQDwjjDigTVnhAmsAAD0G2HEA3btBQDAO8KIBz4qsAIA4BlhxAMqsAIA4B1hxAMqsAIA4B1hxAMqsAIA4B1hxAOftZomxQ0BAGAAI4x44LdW06S2HQAADGSEEQ+YMwIAgHeEEQ/cc0a+89yfdUl5hY6fbE1hqwAAGFgIIx7Yd+091tSq57Z8ogP1zdpeczyl7QIAYCAhjHhgr8BasaPOmjtyuLEldY0CAGCAIYx4YK/A+ocdddbrh08QRgAA6CvCiAfh1TSnWoN6/YMj1uv0jAAA0HeEEQ/8nWnkjd1HdKotaL0eSxjZf/yUGpvb4t42AAAGCsKIB50dI9p96IQkKW94lqS+h5HDjS266seV+h+PbUpE8wAAGBAIIx6EK7CG/fX08ZL6Pmdk75EmtQZD2lXbEPe2AQAwUBBGPPA7s4jmfK5AUt97Ro41ddQjaW4L6VRrsJezAQAYnAgjHvhtPSMTRw/VBeNzJUmNze1qbus9XHxqK472KYXSAABpijDigX2UZkbRKI3IylBWRsct7UvvSLhnxP0YAIB0QhjxwD5n5KIzR8vn82nsiM5JrH2YN/KpLYAcP8mKGgBAeiKMeGCfMjKjaJQkWWHkUEMfwogtgBxjmAYAkKYIIx4cOH7Kevy5zvkiY4fH0DNy0t4zQhgBAKQnwogHf/7kuPU4e0hAUlfPCHNGAADoG8KIB1//4tmSpBsunmC95g4jn3x6Uov/fbM27ukoF/9PGz7QlT9+VYcam109I8wZAQCkp4xUN2Ag+9tZEzV1wkh9Jn+49Zo7jDzy+w+04f06tbSHdMk5eXpmc40O1jeras9RekYAABBhxBOfz2fVFgmzzxk51NCsl94+IEn6sK5Rjc1tOljfLEnad+SkGpvbreuoMwIASFcM08RZuGfkSGOL/u+bH6staCRJB+ubtb3muHXeO/uPO64jjAAA0hVhJM7CYaS2oVm/+OM+x7F179Raj//8Sb3j2KdNzBkBAKQnwkic5Y/I1uicIQqGjBpb2lU0ZqhKzj5DkvS797rCSHhOSWag4z8BPSMAgHTFnJE4y8zw67d3XK7tNcdVf6pVxZPP0C+r9qnqo6MRJ6lOysvRB3UndLI1qOa2oLVEGACAdEEYSYDCkdm6ZmSh9fy8ghFRzz1zzDDtOdykYMjo+Mk2FY4MqKmlXQfrmx2rdAAAGKwYpkmCc12hYnTOEOvxmGFDrOfhoZplz7+j0pWv6Q/v1yWvkQAApAhhJAnOtfWMnDEsU1MnjLSejx6WqdE5mZI6Ns5rbQ/pDzs6Qsj/qfhQxpiI7xkMGWqTAAAGBcJIEowcOkQFuR2rbM4tGK6Jo3OsY2NybGHkZJve/uS4TrYGJUnv7K/XH3cfjfie5et2aNYPN+j/fXg44vFdtY1qC4bi+TUAAEgIwkiSnJs/wvo9cfRQ6/XRwzI1eljHMM2xk63auKcjfPg7twT+SeVuSR0b6d31zJ+1/t1aNbcF9dSmaoWM9Pgbe7t91rObazR31esqX7czkV8JAIC4IIwkyZXnj5UkXXZunorGRO4ZOd7Uau1hc/uV5yjD79PGPUf16s5Deui3O/WfWz/Rd577s369fb+aOntPXvvgsGo7q7pKkjFGj3UGlLV/qlZTS1eVVztjjLZ8fCzqcQAAkoUwkiRfv+xsvf29OZrzuUIVdesZ6QgjB+qbtfXj45Kkr8ws0tcumSRJ+tazf9bazTWSpIbmdq34r/es60NGen7bJ6o5dlJ1Dc16+5N67axtlCQ1tQatcvR2xhg98Jv39eWfVmnev77hCDORHGpo1upXd+tg/al+f38AAKJhaW8S5WZ3DMc4ekaGZVqraSp21Kk1GNK4kdmadEaO7ppzvjbsqNPHR09Kks4ck6PqYyfV3NYxF+SWL07WY2/s1b9U7NbD63cpJzOgC8Z17JUzPCtDJ1ra9e9VH+sPOw6pYked/D6fisbk6LPjRljVYD863KS//beN+o//WaxJecO6tbm5Laiv/eJPev9gg57f+oleXHKpRmQP6XYeAAD91a+ekdWrV2vSpEnKzs5WcXGxNm3a1OP5zz77rKZMmaLs7GxNmzZN69at61djB4szhmXq7LxhGjMsU+NGZqsgN1uSdKizKmvJOWfI5/NpaGZAP/ryhZI6wsXTt35BZ53REWTOLxihsr84TzmZAZ1q6xiyOdka1OaPP5Ukld8wTRl+n9470KAN79cpZKT2kNHeI01WEFly1Tk6c0yOao6d0vWr/6j17x7Uu/vr9erOQ3r09Y/071X7dM9/vq33DzZIkvYcbtL/fmqbNu45oq3Vn+q1Dw7rN38+oLV/qtbuQx29MUdOtOjNj46qubNNAAD0xmeirR2NYu3atVqwYIHWrFmj4uJirVq1Ss8++6x27dql/Pz8budv3LhRl19+ucrLy/VXf/VXevLJJ/WjH/1IW7du1dSpU/v0mQ0NDRo5cqTq6+uVm5vb+wUDwMnWdrUFjUYOHaKTre36PxUfaldto5pa2rVi3uccy3+3fPypcrMzdG7BCK1/t1Z3PL1N5TdM0w0XT1TFjjpt+fhTXT9jgv7t9T16fut+nTN2mP5QdoWWPrVNL799UOeMHaZH/vsM5Y/I0qa9x/Tbdw/q4jNH639dcY4ONTTr1v/Y4tjEz83nk+6+ZopWbvhAre2RV+j4fNLsSWO0rea4WttDGjsiS1++eKJGZGco4Pcp4PPJ7/cp4FPHc79fAX/HzscWIx1qbNb+46c0OidTE0fnqC0YUmt7SDlZAYVCRocbW+Tz+XTG8EyrlH74LXzySdbjrvf22dpoP9d67PN1nt/1us96X/tz23m+rs+zH1OE91G393V/Rg+f42hn52e62hCpvfZ7EO29evruXfcxervkaFf0z4p0T+znhtsBYPDp67/fMYeR4uJiff7zn9e//uu/SpJCoZCKior093//97rnnnu6nT9//nw1NTXppZdesl77whe+oBkzZmjNmjVx/TLpzhijV3Ye0nkFI1Q0JkdNLe16/YPDuvy8sRqWFX1ErqU9qH94eYdefvugMgI+jc7J1Dn5w9XSFlL1sSbN//yZuuWLk/XaB4f1b6/tUV1Ds1raQxqRPUQjsjved9PeY9b7DcsMWBNsgVhEDT6SLfg5Q1nnoc7nzgBqf9LtnD5caw+Lka8JP4983P6+7vfs7Vr7da5mRG1ztPd0fn6Ua/rwXRT18/rWnsjfIcrnevkuvRy3n9Xn/6Z9+i6xtcf5Hv1rT7++i6s9Ybd8cbJjGkE89PXf75jmjLS2tmrLli1atmyZ9Zrf71dpaamqqqoiXlNVVaWysjLHa3PnztWLL74Yy0ejD3w+n67+bIH1fFhWhq6dNq7X67IyAvr+9VP1/et77qm64ryxuuK8sRGP7axtUMWOQ7r4zNGaedZo/Xr7fm2tPq5gKKRgSAoZo2DIKGiMQiGj9lDH75Axjv9BjM7J1ITRQ3WsqUUHjjcre4hfmQG/mlqD8knK69wV+dOmVrUFjSSjcJw2klUkruNx99fleL3jWmNsjzsvsD83xljvZzrfoOt513t0a0OU95GJ3NZu7xXhc5zfLXIbFeWz7O/V1b7I39d9D5PFfo9trya3EUCaun7G+LiHkb6KKYwcOXJEwWBQBQUFjtcLCgq0c2fkmha1tbURz6+trY14viS1tLSopaXFet7Q0BBLM5ECUwpzNaWwK/X+7awi/e2sohS2CPFkTIRQpQhByR3s5ApKvRw3nekpWnAKt8PZts7ftnOtY7bPcD53nmEPer29b0+f1/3zI79/X9sT6Zxo11r/VWL5LlHaI/d7KtL3j8N36aU97s+OeI2X79LH9sj9no7Pj/bfox/fpZf2dL1HYr5LeP5iKpyWq2nKy8v1wAMPpLoZADqF57l0PktlUwAMQjGtpsnLy1MgEFBdnXMDt7q6OhUWFka8prCwMKbzJWnZsmWqr6+3fmpqamJpJgAAGEBiCiOZmZmaOXOmKioqrNdCoZAqKipUUlIS8ZqSkhLH+ZK0YcOGqOdLUlZWlnJzcx0/AABgcIp5mKasrEwLFy7UrFmzNHv2bK1atUpNTU1atGiRJGnBggWaMGGCysvLJUl33HGHrrjiCj3yyCO67rrr9PTTT2vz5s362c9+Ft9vAgAABqSYw8j8+fN1+PBhLV++XLW1tZoxY4bWr19vTVKtrq6W39/V4XLJJZfoySef1H333ad7771X5557rl588cU+1xgBAACDW8x1RlKBOiMAAAw8ff33m43yAABAShFGAABAShFGAABAShFGAABAShFGAABAShFGAABAShFGAABAShFGAABASp2Wu/a6heuyNTQ0pLglAACgr8L/bvdWX3VAhJHGxkZJUlFRUYpbAgAAYtXY2KiRI0dGPT4gysGHQiEdOHBAI0aMkM/ni9v7NjQ0qKioSDU1NZSZTzDudXJwn5OHe50c3OfkScS9NsaosbFR48ePd+xb5zYgekb8fr8mTpyYsPfPzc3lD3mScK+Tg/ucPNzr5OA+J0+873VPPSJhTGAFAAApRRgBAAApldZhJCsrSytWrFBWVlaqmzLoca+Tg/ucPNzr5OA+J08q7/WAmMAKAAAGr7TuGQEAAKlHGAEAAClFGAEAAClFGAEAACmV1mFk9erVmjRpkrKzs1VcXKxNmzalukkD2ve+9z35fD7Hz5QpU6zjzc3NWrJkic444wwNHz5cX/7yl1VXV5fCFg8cr7/+uubNm6fx48fL5/PpxRdfdBw3xmj58uUaN26chg4dqtLSUn344YeOc44dO6abb75Zubm5GjVqlG655RadOHEiid/i9Nfbff7a177W7c/4Nddc4ziH+9y78vJyff7zn9eIESOUn5+vL33pS9q1a5fjnL78fVFdXa3rrrtOOTk5ys/P17e//W21t7cn86uc9vpyr6+88spuf65vu+02xzmJvtdpG0bWrl2rsrIyrVixQlu3btX06dM1d+5cHTp0KNVNG9A+97nP6eDBg9bPG2+8YR2788479Zvf/EbPPvusXnvtNR04cEA33HBDCls7cDQ1NWn69OlavXp1xOMPP/yw/vmf/1lr1qzRW2+9pWHDhmnu3Llqbm62zrn55pv13nvvacOGDXrppZf0+uuv69Zbb03WVxgQervPknTNNdc4/ow/9dRTjuPc59699tprWrJkid58801t2LBBbW1tmjNnjpqamqxzevv7IhgM6rrrrlNra6s2btyoX/7yl3riiSe0fPnyVHyl01Zf7rUkLV682PHn+uGHH7aOJeVemzQ1e/Zss2TJEut5MBg048ePN+Xl5Sls1cC2YsUKM3369IjHjh8/boYMGWKeffZZ67UdO3YYSaaqqipJLRwcJJkXXnjBeh4KhUxhYaH58Y9/bL12/Phxk5WVZZ566iljjDHvv/++kWT+9Kc/Wef89re/NT6fz+zfvz9pbR9I3PfZGGMWLlxorr/++qjXcJ/759ChQ0aSee2114wxffv7Yt26dcbv95va2lrrnJ/+9KcmNzfXtLS0JPcLDCDue22MMVdccYW54447ol6TjHudlj0jra2t2rJli0pLS63X/H6/SktLVVVVlcKWDXwffvihxo8fr7PPPls333yzqqurJUlbtmxRW1ub455PmTJFZ555Jvfco71796q2ttZxb0eOHKni4mLr3lZVVWnUqFGaNWuWdU5paan8fr/eeuutpLd5IKusrFR+fr7OP/983X777Tp69Kh1jPvcP/X19ZKkMWPGSOrb3xdVVVWaNm2aCgoKrHPmzp2rhoYGvffee0ls/cDivtdhv/rVr5SXl6epU6dq2bJlOnnypHUsGfd6QGyUF29HjhxRMBh03FhJKigo0M6dO1PUqoGvuLhYTzzxhM4//3wdPHhQDzzwgC677DK9++67qq2tVWZmpkaNGuW4pqCgQLW1talp8CARvn+R/jyHj9XW1io/P99xPCMjQ2PGjOH+x+Caa67RDTfcoMmTJ2vPnj269957de2116qqqkqBQID73A+hUEjf/OY3demll2rq1KmS1Ke/L2prayP+mQ8fQ3eR7rUk3XTTTTrrrLM0fvx4vf3227r77ru1a9cuPf/885KSc6/TMowgMa699lrr8YUXXqji4mKdddZZeuaZZzR06NAUtgyIj7/7u7+zHk+bNk0XXnihzjnnHFVWVurqq69OYcsGriVLlujdd991zC9DYkS71/Y5TdOmTdO4ceN09dVXa8+ePTrnnHOS0ra0HKbJy8tTIBDoNjO7rq5OhYWFKWrV4DNq1Cidd9552r17twoLC9Xa2qrjx487zuGeexe+fz39eS4sLOw2Obu9vV3Hjh3j/ntw9tlnKy8vT7t375bEfY7V0qVL9dJLL+nVV1/VxIkTrdf78vdFYWFhxD/z4WNwinavIykuLpYkx5/rRN/rtAwjmZmZmjlzpioqKqzXQqGQKioqVFJSksKWDS4nTpzQnj17NG7cOM2cOVNDhgxx3PNdu3apurqae+7R5MmTVVhY6Li3DQ0Neuutt6x7W1JSouPHj2vLli3WOa+88opCoZD1Fw9i98knn+jo0aMaN26cJO5zXxljtHTpUr3wwgt65ZVXNHnyZMfxvvx9UVJSonfeeccR/jZs2KDc3FxdcMEFyfkiA0Bv9zqS7du3S5Ljz3XC73VcpsEOQE8//bTJysoyTzzxhHn//ffNrbfeakaNGuWYLYzY3HXXXaaystLs3bvX/PGPfzSlpaUmLy/PHDp0yBhjzG233WbOPPNM88orr5jNmzebkpISU1JSkuJWDwyNjY1m27ZtZtu2bUaSWblypdm2bZv5+OOPjTHGPPTQQ2bUqFHm17/+tXn77bfN9ddfbyZPnmxOnTplvcc111xjLrroIvPWW2+ZN954w5x77rnmxhtvTNVXOi31dJ8bGxvNt771LVNVVWX27t1r/vCHP5iLL77YnHvuuaa5udl6D+5z726//XYzcuRIU1lZaQ4ePGj9nDx50jqnt78v2tvbzdSpU82cOXPM9u3bzfr1683YsWPNsmXLUvGVTlu93evdu3eb73//+2bz5s1m79695te//rU5++yzzeWXX269RzLuddqGEWOM+Zd/+Rdz5plnmszMTDN79mzz5ptvprpJA9r8+fPNuHHjTGZmppkwYYKZP3++2b17t3X81KlT5hvf+IYZPXq0ycnJMX/zN39jDh48mMIWDxyvvvqqkdTtZ+HChcaYjuW9999/vykoKDBZWVnm6quvNrt27XK8x9GjR82NN95ohg8fbnJzc82iRYtMY2NjCr7N6aun+3zy5EkzZ84cM3bsWDNkyBBz1llnmcWLF3f7PzDc595FuseSzC9+8QvrnL78fbFv3z5z7bXXmqFDh5q8vDxz1113mba2tiR/m9Nbb/e6urraXH755WbMmDEmKyvLfOYznzHf/va3TX19veN9En2vfZ2NBQAASIm0nDMCAABOH4QRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUoQRAACQUv8fi6HwOhudHzYAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -259,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -272,12 +272,12 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { - "image/png": "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PwYgPT2d0aNHk56eHuHIhBCi6Zo8svTNN99w3XXXNfj8ddddh9vt5uOPP6ZNmzYhCU4IEdsqKir48ssvATjjjDMYN26cFEpCiJjT5JElv9+PyWRq8HmTyYTNZqN169YhCUwIEfuSkpIYNmwYXq+XHj16RDocIYRoliaPLHXr1o133nmnwefnz59Pt27dQhKUECI2aZrGhx9+yNatWwPHTjvtNCmUhBAxrcnF0u23385f/vIX/vWvf+Hz+QLHfT4fTz/9NA888AC///3vwxIkQElJCddeey1Op5Pk5GRuvvlmKisrG21/xx130Llz58CI15133klZWVmddoqiHPPv9ddfD1seQsSr8vJyXn75ZT799FPefvtt3G53pEMSQoiQaPJluLFjx/Ldd98xYcIEJk2aRF5eHrqus23bNiorK7nzzju54YYbwhbotddey/79+1m6dCler5cbb7yR8ePH89prr9Xbft++fezbt48ZM2bQtWtXdu7cya233sq+ffsoLCys0/bFF19kyJAhgcfJyclhy0OIeLRlyxbee+89qqurMZvNDBkyRFbiFkLEjaDWWZoxYwajRo3if//7H5s3bwbg/PPP5+qrr+bss88OS4AAGzduZNGiRXz99df06dMHgKeeeopLL72UGTNmkJ2dfcxrTj/9dN56663A47y8PB599FF++9vf4vP5MBr/f+rJycmyF5UQzeD3+9m3bx/r1q0Dau+OHTVqFKmpqZENTAghQqjJxdL333/P6aefztlnnx3Wwqg+K1euJDk5OVAoAQwcOBBVVVm1ahUjRoxoUj9lZWU4nc46hRLUXmK85ZZbaN++Pbfeeis33nhjo+u/uN3uOpcYysvLAfB6vXi93mBSa9TRvkLZZ7SJ9xzjOT+Px8Nrr73GgQMHAOjTpw8XX3wxRqMxrvKN53MIkl88iPccw5lfU/tscrHUo0cPzjrrLG655RbGjBlDYmJis4MLVlFRERkZGXWOGY1GUlNTKSoqalIfhw4dYtq0aYwfP77O8alTp3LxxRdjt9tZsmQJv//97wOXFRsyffp0pkyZcszxJUuWYLfbmxRPMJYuXRryPqNNvOcYj/npuk51dTWqqtK6dWt8Ph9LliyJdFhhE4/n8Jckv9gX7zmGIz+Xy9Wkdoqu63pTGn766ae8+OKLFBYWomkaI0eO5JZbbuG8885rdpD33XcfTzzxRKNtNm7cyLx583j55ZfZtGlTnecyMjKYMmUKt912W6N9lJeXM2jQIFJTU3n33XcbXQJh8uTJvPjii+zevbvBNvWNLOXm5nLo0KHANjCh4PV6Wbp0KYMGDWo05lgW7znGW35+vx+v14vVagWgqqqKJUuWcNlll8VFfvWJt3P4a5Jf7Iv3HMOZX3l5OWlpaYErTw1p8sjSeeedx3nnncdTTz3Fm2++yUsvvcQFF1xAhw4duPnmmxk7dmzQ837++Mc/HndSePv27cnKygoM9R/l8/koKSk57ntWVFQwZMgQEhMTefvtt4/7hc7Pz2fatGm43e4GJ6haLJZ6nzOZTGH5Rg1Xv9Ek3nOMh/yOHDlCYWEhDoeDMWPGoCgKCQkJWCyWuMjveOI9R8kv9sV7juHIr6n9BTXBGyAhIYEbb7yRG2+8kS1btvDiiy/y9NNP8+CDDzJkyBDefffdJveVnp7epNV8+/XrR2lpKWvWrKF3794AfPjhh2iaRn5+foOvKy8vp6CgAIvFwrvvvhv4a7gx69atIyUlRe7kEeIXNm7cyDvvvIPb7cZqtXLkyBGZxC2EOGUEXSz9UocOHbj//vtp06YNkyZNYsGCBaGKq47TTjuNIUOGMG7cOObMmYPX62XChAmMGTMmcCfc3r17GTBgAK+88gp9+/alvLycwYMH43K5+O9//0t5eXlgInZ6ejoGg4H33nuP4uJizj77bKxWK0uXLuWxxx7jnnvuCUseQsSao/OQvv76awBatWrFqFGjSEpKOu5rNU0DQFXVOv8vhBCxptnF0ieffMILL7zAW2+9haqq/OY3v+Hmm28OZWx1vPrqq0yYMIEBAwagqiojR45k9uzZgee9Xi+bNm0KTNb65ptvWLVqFVBb1P3S9u3badu2LSaTiaeffpq7774bXdfp0KEDM2fOZNy4cWHLQ4hYUVJSwty5cwM3UfTv35+LL74Yg8Fw3Nfqus7mzZt55pln2Lp1K3l5edx222106tSp0TtNhRAiGgVVLO3bt4+XXnqJl156iS1bttC/f39mz57Nb37zGxISEsIVIwCpqakNLkAJ0LZtW345V/3CCy/keHPXhwwZUmcxSiFELV3XefPNNykuLsZutzN8+HA6duzY5NfOnj078EfIUbNnz2bWrFnccccdUjAJIWJKk4ulSy65hGXLlpGWlsb111/PTTfdROfOncMZmxAiQhRF4fLLL2f58uUMHz68yXd5aprG5s2bjymUoLaIuuuuuygoKKBjx45ySU4IETOa/GllMpkoLCxkz549PPHEE1IoCRFnDh06xA8//BB4nJOTw/XXXx/0chjPPPNMg6O6uq7zzDPPnFCcQghxsjV5ZCmYu9yEELFl/fr1vP/++2iaRmpqarO3/1FVla1btzbaZtu2bTKqJISIKSd0N5wQIrZ5vV4WLlwY2NutXbt2JzT/UNM08vLyGm3Tvn17NE2TgkkIETPk00qIU9SBAwd47rnnWLduHYqicOGFF/Lb3/72hLcyuu222xqcwK0oynFX3BdCiGgjxZIQp6B169bx3HPPcfDgQRwOB9dffz0XXHDBCY/2qKpKp06dePLJJ48pmBRFYdasWXTq1ElGlYQQMUUuwwlxCiorK8Pn85GXl8eIESNCuvSHoijceeedDB5cwLPPzmHbtm20b9+e3/3uVrp06SzLBgghYo4US0KcInRdDxQq5513HikpKXTv3j0sxcv27UeorHTw97//HYPBgN/v57vviikrc5OcfPxth4QQIppIsSREnNN1nW+++Ya1a9cyduxYTCYTqqrSo0ePsL7v//3fep57bg0tWtgpLq4kJyeRSZPOD+t7CiFEOMjEASHimNvtZt68ebz//vvs3buXtWvXnpT3TU210batE1VVOXzYhdVqJC8vFbNZ/j4TQsQe+eQSIk7t37+fwsJCSkpKUFWViy++mLPOOuukvLfJZCA93cHBg9V4PH5sNiOZmY7jbkEkhBDRSIolIeKMrut8/fXXLFmyBL/fT1JSEiNHjiQ3N/ekxeByefH7dTIzEzAYVPx+DZfLi8+nYTIdfyNeIYSIJlIsCRFnPv74Yz7++GMAOnfuzLBhw7DZbCc1Bo/HT3m5B59Pw+fTA8WSpsnIkhAi9kixJEScOeOMM1izZg3nnHMO+fn5EblV32w2oOsa+/dXYLUaqa720rKlA1WVZQOEELFHiiUhYpyu6+zatYs2bdoAkJSUxB133IHZbI5YTGazAbPZiKbpeDwaABaLUYolIURMkmJJiBhWXV3NO++8w6ZNmxgzZgydO3cGiGihBODzaaSl2TAYMnC7fZjNBhITLcj8biFELJJiSYgYtWfPHgoLCykrK8NgMOByuSIdUoDBoJCYaCE93YHRqOJyebFYVGTxbiFELJJiSYgYo+s6X3zxBR9++CGappGamsqoUaNo2bJlpEMLsNvNZGYm8NNPh/F6NaxWI927Z2I2y51wQojYI8WSEDHE5XIxf/58Nm/eDMDpp5/OZZddhsViiXBkdRkMCj6fRkWFB6/Xj8/nj3RIQgjRbFIsCRFDduzYwebNmzEajQwZMoQzzzwzKjemdbm8HD5cTYcOqdhsJkpKqjl4sIp27VJkdEkIEXOkWBIihnTt2pWLLrqIzp07k5mZGelwjstgUDGZDBiNKpqGzFkSQsQk2RtOiChWVVXFvHnzqKysDBw7//zzo75QsttN5OQkUlJSzd695Xg8Plq1cmI0ykeOECL2yMiSEFFqx44dvPXWW1RWVuJ2u7n66qsjHVKTGQwqnTun4XRaqa724nRayMpKjMpLhkIIcTxSLAkRZTRN45NPPuGTTz5B13XS09MZMGBApMMKWu0ClHpgbSWpk4QQsUqKJSGiSGVlJfPmzWP79u0A9OrVi0svvRSTyRThyIKjaTorV+7mu++K8Xj82O1m+vfP5fTTo/vyoRBC1EeKJSGiRFFREf/973+pqqrCZDJx2WWX0aNHj0iH1Sz791fw9dd78Xp1LBYDxcVVfPnlbtq1SyYhIbqWORBCiOORYkmIKJGSkoLVasXhcDBq1CjS0tIiHVKzlZa62bmzjNRUG36/RmWlm927fVRX+0lIiHR0QggRHCmWhIigqqoq7HY7iqJgsVi49tprcTgcMXfZ7dfM5tq73g4fdpGQYKGsrAaz2YHJJHfDCSFij3xyCREhmzdv5l//+hdffvll4FhKSkrMF0oATqeZVq2c6DpUVroxmRTatk2SYkkIEZNkZEmIk8zv9/Phhx/yxRdfALBhwwby8/NR1fgpJKxWE7m5tesq+f0aBoOBli0TZZ0lIURMkmJJiJOorKyMt956i927dwNw1llnMXjw4LgqlKB2mQC73YTXq/18N5yC3W6SdZaEEDEpZj6hS0pKuPbaa3E6nSQnJ3PzzTfXWdW4PhdeeCGKotT5d+utt9Zps2vXLoYOHYrdbicjI4M//elP+Hy+cKYiTlGbNm1izpw57N69G4vFwujRo7n00ksxGuPvbxa/X2PXrnJKSmrweHwcPFhFUVHjP69CCBGtYuZT+tprr2X//v0sXboUr9fLjTfeyPjx43nttdcafd24ceOYOnVq4LHdbg/8v9/vZ+jQoWRlZfHFF1+wf/9+rr/+ekwmE4899ljYchGnnvLyct588000TSM7O5tRo0aRkpIS6bDCpqrKS0mJC6MRFEVF1/0cOFCF1+vHZJKNdIUQsSUmiqWNGzeyaNEivv76a/r06QPAU089xaWXXsqMGTPIzs5u8LV2u52srKx6n1uyZAk//PADy5YtIzMzk169ejFt2jT+/Oc/8/DDD2M2m8OSjzj1OJ1OBg4cSFlZGYMGDcJgiO+CQdehrKwGl8uDyWTE5fLhdJrj7nKjEOLUEBPF0sqVK0lOTg4USgADBw5EVVVWrVrFiBEjGnztq6++yn//+1+ysrK4/PLLefDBBwOjSytXrqR79+51NiUtKCjgtttuY8OGDZxxxhn19ul2u3G73YHH5eXlAHi9Xrxe7wnl+ktH+wpln9EmnnP88ccfSUxMBGrzO/r9q2kamqZFMrSQafj8+bHbjVRWutE0P4qiYbWq+P1evF795Ad6AuL5exQkv3gQ7zmGM7+m9hkTxVJRUREZGRl1jhmNRlJTUykqKmrwdddccw1t2rQhOzub9evX8+c//5lNmzYxb968QL+/3r396OPG+p0+fTpTpkw55viSJUvqXOYLlaVLl4a8z2gTTzlqmsa+ffs4dOgQFouFTp06xVV+9akvv9rasHZ/uNrpkUdYtmzJyQ0shE7FcxhP4j0/iP8cw5Gfy+VqUruIFkv33XcfTzzxRKNtNm7c2Oz+x48fH/j/7t2707JlSwYMGMDWrVvJy8trdr+TJk1i4sSJgcfl5eXk5uYyePBgnE5ns/v9Na/Xy9KlSxk0aFBcrL1Tn3jLsaSkhPnz53Po0CEAevbsidvtjpv8fq2h83fokIt33tnI4cMuDAYVj8dPXl4Kw4efhtkcE3+jBcTb9+ivSX6xL95zDGd+R68MHU9EP7X++Mc/csMNNzTapn379mRlZXHgwIE6x30+HyUlJQ3OR6pPfn4+AFu2bCEvL4+srCy++uqrOm2Ki4sBGu3XYrFgsRy7v5XJZArLN2q4+o0m8ZDj999/z3vvvYfH48FmszFixAjatm3LwoUL4yK/xvw6P4fDgqoaKCvzoOsqqlr7c2O1WjAYYnPe0ql2DuNNvOcH8Z9jOPJran8RLZbS09NJT08/brt+/fpRWlrKmjVr6N27NwAffvghmqYFCqCmWLduHQAtW7YM9Pvoo49y4MCBwGW+pUuX4nQ66dq1a5DZiFOVz+dj0aJFrFmzBoDWrVszcuRInE5n3M4hOB6Px4/PV7sYpaIo6LqG13v0WGwWS0KIU1dMfGqddtppDBkyhHHjxvHVV1/x+eefM2HCBMaMGRO4E27v3r106dIlMFK0detWpk2bxpo1a9ixYwfvvvsu119/Peeff35gJ/fBgwfTtWtXrrvuOr799lsWL17MAw88wO23317vyJEQ9VFVlZKSEgDOO+88xo4dG9LLsbHI5fJSWurGbjeTmGjGaFQ5csSFzxcfE9uFEKeWmJk88OqrrzJhwgQGDBiAqqqMHDmS2bNnB573er1s2rQpMFnLbDazbNkyZs2aRVVVFbm5uYwcOZIHHngg8BqDwcD777/PbbfdRr9+/UhISGDs2LF11mUSoiGapqGqKqqqcuWVV1JcXHxCc+HiiaLU7glXXFyF36+hKArJybZIhyWEEM0SM8VSampqowtQtm3bFl3//7ck5+bm8vHHHx+33zZt2rBw4cKQxChODV6vl4ULF2IwGLjssssAcDgcOByOCEcWPTQNKitrqKnxYbdbKC+vpry8BtntRAgRi2KmWBIiGhw8eJC5c+dy8OBBFEUhPz+/SfPuTjV+v47DYSUpyY6iKKSlWbHbLT/vExfp6IQQIjhSLAnRROvWrWPBggX4fD4cDgdXXnmlFEoNsFqN5OQkYTIpWCxGjhypoUULGxZLfK9cLoSIT1IsCXEcHo+HhQsX8u233wK1y1mMGDFCLrs1IjMzgV69Mvn22wPU1LhxOMz07p2DzSZbCAkhYo8US0I0Qtd1/vvf/7J7924UReHCCy/kvPPOQ5HJN41SVZV+/XLJyXFSU+PD6bSQnX1q3yEohIhdUiwJ0QhFUTjnnHNYsGABI0eOpE2bNpEOKWaoqkrbtimRDkMIIU6YFEtC/Irb7ebQoUPk5OQA0LlzZ9q3bx/XK+OGi67raJouC1EKIWKaFEtC/ML+/fspLCykurqa3/3udyQlJQFNXxJf/H/V1V4OHKjC6/Vjs5nIyEjAZJIJ3kKI2CPFkhDUjoCsXr2axYsX4/f7SUpKwuVyBYolERyfT2P//kpqanxYrbV3wwHk5Mi8JSFE7JFiSZzyampqeO+99/jhhx+A2stuw4YNw2aTFaeby+v143J50HUoLa1BVRVcLg9+v+wNJ4SIPVIsiVPa3r17KSwspLS0FFVVGTRoEPn5+XK32wkyGFQqKjwcPOjCajXgcnnJy0tFVeXrKoSIPVIsiVPaunXrKC0tJTk5mVGjRgUmdYsTYzKpaJpGSYkLRVFQVTAaFSlChRAxSYolcUobPHgwJpOJ888/H6vVGulw4obXqwGQlGTFbjdRVeXF6629M05Gl4QQsUYmD4hTyp49e3jnnXfQtNpf5iaTicGDB0uhFGI+n4bDYaF9+xSSk620bZuE2azi92uRDk0IIYImI0vilKDrOl988QUffvghmqaRlZVFfn5+pMOKWwaDgt1uQlEUWrSwU1Hhxmo1yuRuIURMkmJJxD2Xy8X8+fPZvHkzAN26daNXr16RDSrOWSxGMjISOHiwiooK98+PHXIJTggRk6RYEnFt165dvPXWW5SXl2MwGLjkkks488wzZaLxSXB0vpLfr2M0qhiNMqokhIhNUiyJuPXNN9/w/vvvo+s6LVq0YPTo0WRmZkY6rFOKyWRAFj8XQsQ6KZZE3MrOzkZVVbp168bQoUMxm82RDkkIIUQMkmJJxJWKigoSExMByMrK4tZbb6VFixZy2U0IIUSzySQCERc0TWPFihXMnj2bvXv3Bo6npaVJoSSEEOKEyMiSiHkVFRW8/fbbbN++HYBNmzbJStxCCCFCRoolEdO2bt3K22+/TVVVFSaTiaFDh9KzZ89IhyWEECKOSLEkYtLRy26ffvopABkZGYwePZq0tLQIRyaEECLeSLEkYtL3338fKJTOPPNMhgwZgknuURdCCBEGUiyJmNS9e3c2b95M586dOf300yMdjhBCiDgmd8OJmOD3+/n888/xeDwAKIrCyJEjpVCKYrquU1npoayshupqb6TDEUKIZpORJRH1ysrKeOutt9i9ezcHDhxgxIgRkQ5JNMHhwy4OHnTh9+uYTCrZ2YkkJloiHZYQQgRNiiUR1TZt2sT8+fOpqanBYrHQuXPnSIckmsDn0zhypAaz2YDNZqKiwk1JSbUUS0KImCTFkohKfr+fZcuW8eWXXwK1W5eMGjWKlJSUCEcmmkLXdYDAgqCKogSOCSFErJFiSUSdsrIy5s6dG1iJOz8/n0GDBmEwGCIcmWgqk8lAcrKVAweqqK72YjAopKY6Ih2WEEI0ixRLIuqoqkppaSlWq5Vhw4bRpUuXSIckmiEtzY7VasTn0zCbDSQkyEbGQojYFDN3w5WUlHDttdfidDpJTk7m5ptvprKyssH2O3bsQFGUev/NnTs30K6+519//fWTkZL4BU3TAv+fmJjIVVddxe9+9zsplGKYoigkJlpISbFJoSSEiGkxUyxde+21bNiwgaVLl/L+++/zySefMH78+Abb5+bmsn///jr/pkyZgsPh4JJLLqnT9sUXX6zTbvjw4WHORvyS2+3mpZdeYsOGDYFjubm5JCcnRy4oIYQQ4mcxcRlu48aNLFq0iK+//po+ffoA8NRTT3HppZcyY8YMsrOzj3mNwWAgKyurzrG3336b3/zmNzgcdedOJCcnH9NWnBw//PADmzZtQtM0li9fTpcuXWRukhBCiKgSE8XSypUrSU5ODhRKAAMHDkRVVVatWtWkdXfWrFnDunXrePrpp4957vbbb+eWW26hffv23Hrrrdx4442Bu3jq43a7cbvdgcfl5eUAeL1evN7QLb53tK9Q9hktvF4vy5YtY+3atQDk5OQwYsQINE2rc0ku1sXzOYT4zw/iP0fJL/bFe47hzK+pfcZEsVRUVERGRkadY0ajkdTUVIqKiprUx/PPP89pp51G//796xyfOnUqF198MXa7nSVLlvD73/+eyspK7rzzzgb7mj59OlOmTDnm+JIlS7Db7U2KJxhLly4NeZ+RVFNTw44dO6ipqQFqN8FNS0vjs88+i3Bk4RNv5/DX4j0/iP8cJb/YF+85hiM/l8vVpHYRLZbuu+8+nnjiiUbbbNy48YTfp7q6mtdee40HH3zwmOd+eeyMM86gqqqKv/3tb40WS5MmTWLixImBx+Xl5eTm5jJ48GCcTucJx3uU1+tl6dKlDBo0KG42ia2srGTOnDl4PB7sdjuXXnopW7Zsiascfykez+EvxXt+EP85Sn6xL95zDGd+R68MHU9Ei6U//vGP3HDDDY22ad++PVlZWRw4cKDOcZ/PR0lJSZPmGhUWFuJyubj++uuP2zY/P59p06bhdruxWOpfbdhisdT7nMlkCss3arj6jYSUlBTOOOMMiouLufLKK7FarWzZsiWucqyP5Bf74j1HyS/2xXuO4civqf1FtFhKT08nPT39uO369etHaWkpa9asoXfv3gB8+OGHaJpGfn7+cV///PPPc8UVVzTpvdatW0dKSkqDhZII3sGDB7FYLIFRt0GDBqEoCqqqxu01diGEEPEjJuYsnXbaaQwZMoRx48YxZ84cvF4vEyZMYMyYMYE74fbu3cuAAQN45ZVX6Nu3b+C1W7Zs4ZNPPmHhwoXH9Pvee+9RXFzM2WefjdVqZenSpTz22GPcc889Jy23eLdu3ToWLlxIy5YtGTt2LKqqyt1uQgghYkpMFEsAr776KhMmTGDAgAGoqsrIkSOZPXt24Hmv18umTZuOmaz1wgsv0KpVKwYPHnxMnyaTiaeffpq7774bXdfp0KEDM2fOZNy4cWHPJ955PB4WLlzIt99+C9ROyPd4PFit1ghHJoQQQgQnZoql1NRUXnvttQafb9u2bb0bdT722GM89thj9b5myJAhDBkyJGQxilrFxcUUFhZy6NAhFEXhwgsv5Lzzzmt0OQYhhBAiWsVMsSSin67rfPPNNyxatAifz0diYiIjR46kTZs2kQ5NCCGEaDYplkTI+P1+vvrqK3w+Hx06dGD48OEkJCREOiwhhBDihEixJELGaDQyatQofvrpJ/r37y+X3YQQQsQFKZZEs+m6zurVq/F4PJxzzjlA05eDEEIIIWKFFEuiWWpqanjvvff44YcfUBSFDh06kJmZGemwhBBCiJCTYkkEbd++fcydO5fS0lJUVWXgwIHH7N0nhBBCxAsplkST6brOqlWrWLp0KZqmkZyczKhRo8jJyYl0aEIIIUTYSLEkmkTXdebNm8f3338P1K6qfsUVV8gik0IIIeKeFEuiSRRFoXXr1mzcuJHBgwdz1llnyd1uQgghTglSLIkG6bpOZWUliYmJAPTp04e8vDxSU1MjHJkQQghx8qiRDkBEJ5fLxf/+9z9eeOEFampqgNrRJSmUhBBCnGpkZEkcY9euXbz11luUl5djMBjYu3cveXl5kQ5LCCGEiAgplkSArut89tlnfPTRR+i6TosWLRg1ahRZWVmRDk0IIYSIGCmWBABVVVW8/fbbbN26FYDu3bszdOhQLBZLhCMTQgghIkuKJQHAsmXL2Lp1K0ajkUsvvZRevXrJ3W5CCCEEUiyJnw0aNIjy8nIKCgpkNW4hhBDiF+RuuFNUZWUlK1euDDy22+1cd911UigJIYQQvyIjS6egbdu2MW/ePKqqqrDZbPTq1SvSIQkhhBBRS4qlU4imaaxYsYJPP/0UgIyMDNnXTQghhDgOKZZOEeXl5cybN4+dO3cCcOaZZzJkyBBMJlOEIxNCCCGimxRLp4Bt27bx1ltv4XK5MJvNXHbZZXTv3j3SYQkhhBAxQYqlU4Cu67hcLrKyshg1ahQtWrSIdEhCCCFEzJBiKU5pmoaq1t7smJeXx5gxY8jLy8NolFMuhBBCBEOWDohDmzZt4qmnnuLIkSOBY507d5ZCSQghhGgGKZbiiN/vZ/Hixbz++uuUlpYG7noTQgghRPPJUEOcKC0tpbCwkL179wKQn5/PwIEDIxyVEEIIEfukWIoDGzdu5N1336Wmpgar1cqwYcPo0qVLpMMSQggh4oIUSzFu48aNvPnmmwDk5OQwatQokpOTIxuUEEIIEUekWIpxHTt2JDs7mzZt2jBgwAAMBkOkQxJCCCHiihRLMWjr1q20a9cOVVUxGo3ceOONcqebEEIIESZyN1wM8fl8LFiwgP/+97+sWLEicFwKJSGEECJ8YqZYevTRR+nfvz92u73Jc3J0XWfy5Mm0bNkSm83GwIED2bx5c502JSUlXHvttTidTpKTk7n55puprKwMQwYn5vDhw/znP/9h9erVkQ5FCCGEOKXETLHk8XgYPXo0t912W5Nf89e//pXZs2czZ84cVq1aRUJCAgUFBdTU1ATaXHvttWzYsIGlS5fy/vvv88knnzB+/PhwpNBs33//Pc8++yzFxcXY7XauvfZaLr744kiHJYQQQpwSYub6zZQpUwB46aWXmtRe13VmzZrFAw88wLBhwwB45ZVXyMzMZP78+YwZM4aNGzeyaNEivv76a/r06QPAU089xaWXXsqMGTPIzs4OSy5N5fV62bVrF+vWrQOgbdu2XHnllSQmJkY0LiGEEOJUEjPFUrC2b99OUVFRnYUZk5KSyM/PZ+XKlYwZM4aVK1eSnJwcKJQABg4ciKqqrFq1ihEjRtTbt9vtxu12Bx6Xl5cDtcWN1+sNWQ6HDx+mtLQUgHPPPZdzzz0XVVVD+h6RdjSXeMrplyS/2BfvOUp+sS/ecwxnfk3tM26LpaKiIgAyMzPrHM/MzAw8V1RUREZGRp3njUYjqampgTb1mT59emCk65eWLFmC3W4/0dDryM3NxWg0UllZyaJFi0LadzRZunRppEMIK8kv9sV7jpJf7Iv3HMORn8vlalK7iBZL9913H0888USjbTZu3Bh1q1FPmjSJiRMnBh6Xl5eTm5vL4MGDcTqdIXsfr9fL0qVLGTRoECaTKWT9RpN4z1Hyi33xnqPkF/viPcdw5nf0ytDxRLRY+uMf/8gNN9zQaJv27ds3q++srCwAiouLadmyZeB4cXExvXr1CrQ5cOBAndf5fD5KSkoCr6+PxWLBYrEcc9xkMoXlGzVc/UaTeM9R8ot98Z6j5Bf74j3HcOTX1P4iWiylp6eTnp4elr7btWtHVlYWy5cvDxRH5eXlrFq1KnBHXb9+/SgtLWXNmjX07t0bgA8//BBN08jPzw9LXEIIIYSILTGzdMDRu8J27dqF3+9n3bp1rFu3rs6aSF26dOHtt98GQFEU7rrrLh555BHeffddvvvuO66//nqys7MZPnw4AKeddhpDhgxh3LhxfPXVV3z++edMmDCBMWPGRPxOOCGEEEJEh5iZ4D158mRefvnlwOMzzjgDgI8++ogLL7wQgE2bNlFWVhZoc++991JVVcX48eMpLS3l3HPPZdGiRVit1kCbV199lQkTJjBgwABUVWXkyJHMnj375CQlhBBCiKgXM8XSSy+9dNw1lnRdr/NYURSmTp3K1KlTG3xNamoqr732WihCFEIIIUQcipnLcEIIIYQQkSDFkhBCCCFEI6RYEkIIIYRohBRLQgghhBCNkGJJCCGEEKIRUiwJIYQQQjRCiiUhhBBCiEZIsSSEEEII0QgploQQQgghGhEzK3hHs6Mrh5eXl4e0X6/Xi8vlory8PG53ko73HCW/2BfvOUp+sS/ecwxnfkd/b/96B5Bfk2IpBCoqKgDIzc2NcCRCCCGECFZFRQVJSUkNPq/oxyunxHFpmsa+fftITExEUZSQ9VteXk5ubi67d+/G6XSGrN9oEu85Sn6xL95zlPxiX7znGM78dF2noqKC7OxsVLXhmUkyshQCqqrSqlWrsPXvdDrj8gfgl+I9R8kv9sV7jpJf7Iv3HMOVX2MjSkfJBG8hhBBCiEZIsSSEEEII0QgplqKYxWLhoYcewmKxRDqUsIn3HCW/2BfvOUp+sS/ec4yG/GSCtxBCCCFEI2RkSQghhBCiEVIsCSGEEEI0QoolIYQQQohGSLEkhBBCCNEIKZYi6NFHH6V///7Y7XaSk5Ob9Bpd15k8eTItW7bEZrMxcOBANm/eXKdNSUkJ1157LU6nk+TkZG6++WYqKyvDkMHxBRvLjh07UBSl3n9z584NtKvv+ddff/1kpFRHc77WF1544TGx33rrrXXa7Nq1i6FDh2K328nIyOBPf/oTPp8vnKk0KNgcS0pKuOOOO+jcuTM2m43WrVtz5513UlZWVqddpM7h008/Tdu2bbFareTn5/PVV1812n7u3Ll06dIFq9VK9+7dWbhwYZ3nm/IzebIFk+Nzzz3HeeedR0pKCikpKQwcOPCY9jfccMMx52rIkCHhTqNBweT30ksvHRO71Wqt0ybazmEw+dX3eaIoCkOHDg20iabz98knn3D55ZeTnZ2NoijMnz//uK9ZsWIFZ555JhaLhQ4dOvDSSy8d0ybYn+ug6SJiJk+erM+cOVOfOHGinpSU1KTXPP7443pSUpI+f/58/dtvv9WvuOIKvV27dnp1dXWgzZAhQ/SePXvqX375pf7pp5/qHTp00K+++uowZdG4YGPx+Xz6/v376/ybMmWK7nA49IqKikA7QH/xxRfrtPvl1+Bkac7X+oILLtDHjRtXJ/aysrLA8z6fTz/99NP1gQMH6mvXrtUXLlyop6Wl6ZMmTQp3OvUKNsfvvvtOv/LKK/V3331X37Jli758+XK9Y8eO+siRI+u0i8Q5fP3113Wz2ay/8MIL+oYNG/Rx48bpycnJenFxcb3tP//8c91gMOh//etf9R9++EF/4IEHdJPJpH/33XeBNk35mTyZgs3xmmuu0Z9++ml97dq1+saNG/UbbrhBT0pK0vfs2RNoM3bsWH3IkCF1zlVJScnJSqmOYPN78cUXdafTWSf2oqKiOm2i6RwGm9/hw4fr5Pb999/rBoNBf/HFFwNtoun8LVy4UP/LX/6iz5s3Twf0t99+u9H227Zt0+12uz5x4kT9hx9+0J966indYDDoixYtCrQJ9mvWHFIsRYEXX3yxScWSpml6VlaW/re//S1wrLS0VLdYLPr//vc/Xdd1/YcfftAB/euvvw60+eCDD3RFUfS9e/eGPPbGhCqWXr166TfddFOdY035IQu35uZ3wQUX6H/4wx8afH7hwoW6qqp1PtCfeeYZ3el06m63OySxN1WozuGbb76pm81m3ev1Bo5F4hz27dtXv/322wOP/X6/np2drU+fPr3e9r/5zW/0oUOH1jmWn5+v/+53v9N1vWk/kydbsDn+ms/n0xMTE/WXX345cGzs2LH6sGHDQh1qswSb3/E+X6PtHJ7o+XvyySf1xMREvbKyMnAsms7fLzXlM+Dee+/Vu3XrVufYVVddpRcUFAQen+jXrCnkMlwM2b59O0VFRQwcODBwLCkpifz8fFauXAnAypUrSU5Opk+fPoE2AwcORFVVVq1adVLjDUUsa9asYd26ddx8883HPHf77beTlpZG3759eeGFF9BP8pJhJ5Lfq6++SlpaGqeffjqTJk3C5XLV6bd79+5kZmYGjhUUFFBeXs6GDRtCn0gjQvX9VFZWhtPpxGisux3lyTyHHo+HNWvW1Pn5UVWVgQMHBn5+fm3lypV12kPtuTjavik/kydTc3L8NZfLhdfrJTU1tc7xFStWkJGRQefOnbnttts4fPhwSGNviubmV1lZSZs2bcjNzWXYsGF1fo6i6RyG4vw9//zzjBkzhoSEhDrHo+H8NcfxfgZD8TVrCtlIN4YUFRUB1PklevTx0eeKiorIyMio87zRaCQ1NTXQ5mQJRSzPP/88p512Gv37969zfOrUqVx88cXY7XaWLFnC73//eyorK7nzzjtDFv/xNDe/a665hjZt2pCdnc369ev585//zKZNm5g3b16g3/rO8dHnTqZQnMNDhw4xbdo0xo8fX+f4yT6Hhw4dwu/31/u1/fHHH+t9TUPn4pc/b0ePNdTmZGpOjr/25z//mezs7Dq/fIYMGcKVV15Ju3bt2Lp1K/fffz+XXHIJK1euxGAwhDSHxjQnv86dO/PCCy/Qo0cPysrKmDFjBv3792fDhg20atUqqs7hiZ6/r776iu+//57nn3++zvFoOX/N0dDPYHl5OdXV1Rw5cuSEv+ebQoqlELvvvvt44oknGm2zceNGunTpcpIiCr2m5niiqquree2113jwwQePee6Xx8444wyqqqr429/+FpJftOHO75dFQ/fu3WnZsiUDBgxg69at5OXlNbvfYJysc1heXs7QoUPp2rUrDz/8cJ3nwnkORfM8/vjjvP7666xYsaLOJOgxY8YE/r979+706NGDvLw8VqxYwYABAyIRapP169ePfv36BR7379+f0047jWeffZZp06ZFMLLQe/755+nevTt9+/atczyWz1+0kGIpxP74xz9yww03NNqmffv2zeo7KysLgOLiYlq2bBk4XlxcTK9evQJtDhw4UOd1Pp+PkpKSwOtPVFNzPNFYCgsLcblcXH/99cdtm5+fz7Rp03C73Se8f9DJyu+o/Px8ALZs2UJeXh5ZWVnH3MlRXFwMEFPnsKKigiFDhpCYmMjbb7+NyWRqtH0o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35kxYwbr16+noKCAK664gs2bN9dp95e//IV77rmHdevW0alTJ66++mp8Pl+z4xNC1E+KJSFEVJk6dSqDBg0iLy+P1NTU47Z3u9089thjvPDCCxQUFNC+fXtuuOEGfvvb3/Lss8/W+5qcnBxmz57N5MmTSUlJ4eKLL2batGls27Yt0Oa1116jpqaGV155hdNPP52LL76Yf/7zn/zf//0fxcXFzcotPT0dgOTkZLKysgKPf23GjBn8+c9/ZsyYMXTu3JknnniCXr16HTNqdc899zB06FA6derElClT2LlzJ1u2bGlWbEKIhkmxJISIKn369Amq/ZYtW3C5XAwaNCgw98fhcPDKK6+wdevWBl93++23U1RUxKuvvkq/fv2YO3cu3bp1Y+nSpQBs3LiRnj17kpCQEHjNOeecg6ZpdeZZhVp5eTn79u3jnHPOqXP8nHPOYePGjXWO/XLkrWXLlgAcOHAgbLEJcaqSCd5CiKjyy+IEQFVVdF2vc8zr9Qb+/+gcogULFpCTk1OnncViafS9EhMTufzyy7n88st55JFHKCgo4JFHHmHQoEHNiv14sYaayWQK/L+iKEDtfCchRGjJyJIQIqqlp6fXuYsOYN26dYH/79q1KxaLhV27dtGhQ4c6/3Jzc5v8Poqi0KVLF6qqqgA47bTT+PbbbwOPAT7//HNUVaVz585NirW8vJzt27fXaWMymRqcJwXgdDrJzs7m888/r3P8888/p2vXrk3ORwgROlIsCSGi2sUXX8zq1at55ZVX2Lx5Mw899BDff/994PnExETuuece7r77bl5++WW2bt3KN998w1NPPcXLL79cb5/r1q1j2LBhFBYW8sMPP7Blyxaef/55XnjhBYYNGwbAtddei9VqZezYsXz//fd89NFH3HHHHVx33XVkZmY2GOv//d//8emnn/Ldd98xduxYDAZDnTZt27Zl+fLlFBUVceTIkXr7+dOf/sQTTzzBG2+8waZNm7jvvvtYt24df/jDH5rzJRRCnCC5DCeEiGoFBQU8+OCD3HvvvdTU1HDTTTdx/fXX89133wXaTJs2jfT0dKZPn862bdtITk7mzDPP5P7776+3z1atWtG2bVumTJkSuA3/6OO7774bALvdzuLFi/nDH/7AWWedhd1uZ+TIkcycObPBWCdNmsT27du57LLLSEpKYtq0aceMLP39739n4sSJPPfcc+Tk5LBjx45j+rnzzjspKyvjj3/8IwcOHKBr1668++67dOzYsRlfQSHEiVL0X19gF0IIIYQQAXIZTgghhBCiEVIsCSGEEEI0QoolIYQQQohGSLEkhBBCCNEIKZaEEEIIIRohxZIQQgghRCOkWBJCCCGEaIQUS0IIIYQQjZBiSQghhBCiEVIsCSGEEEI0QoolIYQQQohG/D+jYhvA7jiodQAAAABJRU5ErkJggg==", + "image/png": "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Fy485nNWrFjBSSedhM1mo0uXLsybN++wNo19XzeaElEzefJk9eijj6qJEyeq1NTUBj3n4YcfVqmpqWrhwoXqq6++Updeeqnq2LGjqq6uDrUZNmyY6tu3r/r000/VRx99pLp06aKuuuqqCGVRv8bGEggE1J49e+p8TZkyRSUnJ6uKiopQO0DNnTu3Truffw+aS1O+12effbYaN25cndjLy8tDjwcCAdWrVy81ePBgtXbtWrV48WKVmZmpJk2aFOl0jqixOX7zzTfq8ssvV2+88YbavHmzWr58ueratasaOXJknXbROIYvvfSSslqtas6cOWr9+vVq3LhxKi0tTZWUlByx/SeffKJMJpP6y1/+or777jt13333KYvFor755ptQm4a8J5tTY3P89a9/rZ544gm1du1atWHDBnXdddep1NRU9dNPP4XajBkzRg0bNqzOsSotLW2ulOpobH5z585VLperTuzFxcV12sTSMWxsfgcOHKiT27fffqtMJpOaO3duqE0sHb/FixerP/7xj2rBggUKUK+99lq97bdu3aqcTqeaOHGi+u6779Tjjz+uTCaTWrJkSahNY79nTSHFUgyYO3dug4olwzBUTk6O+utf/xraV1ZWpmw2m/rvf/+rlFLqu+++U4D6/PPPQ23efvttpWma2rVrV9hjr0+4YunXr5+6/vrr6+xryJss0pqa39lnn61+97vfHfXxxYsXK13X6/xCf/LJJ5XL5VJerzcssTdUuI7hK6+8oqxWq/L7/aF90TiGp556qrrllltC28FgUOXl5anp06cfsf2vfvUrddFFF9XZV1BQoP7f//t/SqmGvSebW2Nz/KVAIKBSUlLUs88+G9o3ZswYNXz48HCH2iSNze9Yv19j7Rge7/F77LHHVEpKiqqsrAzti6Xj93MN+R1wzz33qJ49e9bZd+WVV6rCwsLQ9vF+zxpCTsPFkW3btlFcXMzgwYND+1JTUykoKGDVqlUArFq1irS0NAYMGBBqM3jwYHRdZ/Xq1c0abzhiWbNmDevWreOGG2447LFbbrmFzMxMTj31VObMmYNq5iXDjie/F154gczMTHr16sWkSZPweDx1+u3duzfZ2dmhfYWFhbjdbtavXx/+ROoRrp+n8vJyXC4XZnPd21E25zH0+XysWbOmzvtH13UGDx4cev/80qpVq+q0h9pjcah9Q96Tzakp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Ukp5PB41dOhQlZWVpSwWi2rfvr0aN25cWD+IGqsx+d1+++2httnZ2erCCy9UX375ZZ3+Yu0YNvZn9Pvvv1eAWrp06WF9xdrxO9rvh0M5jRkzRp199tmHPadfv37KarWqTp061flMPKS+71k4aEo18/XWQgghhBBxRNZZEkIIIYSohxRLQgghhBD1kGJJCCGEEKIeUiwJIYQQQtRDiiUhhBBCiHpIsSSEEEIIUQ8ploQQQggh6iHFkhBCCCFEPaRYEkKIJrruuusYMWLEcffzpz/9KSo33hVCNIwUS0KIZqNpWr1ff/rTn5otlm3btvHrX/+avLw87HY7bdu2Zfjw4Xz//fcRfV1N01i4cGGdfXfddRfLly+P6OsKIZrOHO0AhBAtx549e0L/f/nll5k8eTIbN24M7UtOTg79XylFMBjEbA7/rym/38+QIUPo1q0bCxYsIDc3l59++om3336bsrKysL/esSQnJ9fJXQgRW2RkSQjRbHJyckJfqampaJoW2v7+++9JSUnh7bff5uSTT8Zms/Hxxx8f8VTX7bffzjnnnBPaNgyD6dOn07FjRxwOB3379qWoqOiocaxfv54tW7bwz3/+k9NOO4327dtz+umn8+CDD3LaaaeF2n3zzTecd955OBwOWrVqxfjx46msrDxqvx06dGDmzJl19vXr1y80YtahQwcALrvsMjRNC23/8jScYRhMnTqVtm3bYrPZ6NevH0uWLAk9vn37djRNY8GCBZx77rk4nU769u3LqlWrjhqbEKLppFgSQsSUe++9l4cffpgNGzbQp0+fBj1n+vTpPPfcc8yePZv169dzxx138Jvf/IYPPvjgiO2zsrLQdZ2ioiKCweAR21RVVVFYWEh6ejqff/458+fP591332XChAlNzu3zzz8HYO7cuezZsye0/Ut///vf+dvf/saMGTP4+uuvKSws5NJLL2XTpk112v3xj3/krrvuYt26dZxwwglcddVVBAKBJscnhDgyKZaEEDFl6tSpDBkyhM6dO5ORkXHM9l6vl4ceeog5c+ZQWFhIp06duO666/jNb37DU089dcTntGnThlmzZjF58mTS09M577zzmDZtGlu3bg21efHFF6mpqeG5556jV69enHfeefzjH//gP//5DyUlJU3KLSsrC4C0tDRycnJC2780Y8YMfv/73zN69Gi6devGI488Qr9+/Q4btbrrrru46KKLOOGEE5gyZQo//vgjmzdvblJsQoijk2JJCBFTBgwY0Kj2mzdvxuPxMGTIkNDcn+TkZJ577jm2bNly1OfdcsstFBcX88ILLzBw4EDmz59Pz549WbZsGQAbNmygb9++JCUlhZ5z+umnYxhGnXlW4eZ2u9m9ezenn356nf2nn346GzZsqLPv5yNvubm5AOzduzdisQnRUskEbyFETPl5cQKg6zpKqTr7/H5/6P+H5hAtWrSINm3a1Glns9nqfa2UlBQuueQSLrnkEh588EEKCwt58MEHGTJkSJNiP1as4WaxWEL/1zQNqJ3vJIQILxlZEkLEtKysrDpX0QGsW7cu9P8ePXpgs9nYsWMHXbp0qfOVn5/f4NfRNI3u3btTVVUFwIknnshXX30V2gb45JNP0HWdbt26NShWt9vNtm3b6rSxWCxHnScF4HK5yMvL45NPPqmz/5NPPqFHjx4NzkcIET5SLAkhYtp5553HF198wXPPPcemTZt44IEH+Pbbb0OPp6SkcNddd3HHHXfw7LPPsmXLFr788ksef/xxnn322SP2uW7dOoYPH05RURHfffcdmzdv5plnnmHOnDkMHz4cgKuvvhq73c6YMWP49ttvef/997n11lu55ppryM7OPmqs//nPf/joo4/45ptvGDNmDCaTqU6bDh06sHz5coqLizl48OAR+7n77rt55JFHePnll9m4cSP33nsv69at43e/+11TvoVCiOMkp+GEEDGtsLCQ+++/n3vuuYeamhquv/56rr32Wr755ptQm2nTppGVlcX06dPZunUraWlpnHTSSfzhD384Yp9t27alQ4cOTJkyJXQZ/qHtO+64AwCn08k777zD7373O0455RScTicjR47k0UcfPWqskyZNYtu2bVx88cWkpqYybdq0w0aW/va3vzFx4kSefvpp2rRpw/bt2w/r57bbbqO8vJw777yTvXv30qNHD9544w26du3ahO+gEOJ4aeqXJ9iFEEIIIUSInIYTQgghhKiHFEtCCCGEEPWQYkkIIYQQoh5SLAkhhBBC1EOKJSGEEEKIekixJIQQQghRDymWhBBCCCHqIcWSEEIIIUQ9pFgSQgghhKiHFEtCCCGEEPWQYkkIIYQQoh7/H/E7JiQerfF/AAAAAElFTkSuQmCC", "text/plain": [ "
" ] diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 320fa52..fd754e7 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -5,7 +5,7 @@ from vqls_prototype.matrix_decomposition import ( MatrixDecomposition, SymmetricDecomposition, - PauliDecomposition + PauliDecomposition, ) @@ -23,7 +23,9 @@ def test_decomposition_raises(): MatrixDecomposition(matrix=mat) -@pytest.mark.parametrize("decomposition_t", [SymmetricDecomposition, PauliDecomposition]) +@pytest.mark.parametrize( + "decomposition_t", [SymmetricDecomposition, PauliDecomposition] +) def test_decomposition(symmetric, decomposition_t): decomp = decomposition_t(matrix=symmetric) assert_allclose(decomp.recompose(), symmetric) diff --git a/tests/test_vqls.py b/tests/test_vqls.py index d5631dd..bc2e605 100644 --- a/tests/test_vqls.py +++ b/tests/test_vqls.py @@ -31,6 +31,7 @@ if has_aer(): from qiskit import Aer + class TestVQLS(QiskitTestCase): """Test VQLS""" @@ -38,20 +39,14 @@ def setUp(self): super().setUp() self.seed = 50 algorithm_globals.random_seed = self.seed - + self.options = ( - { - "use_local_cost_function": False, - "use_overlap_test": False - }, + {"use_local_cost_function": False, "use_overlap_test": False}, { "use_local_cost_function": True, "use_overlap_test": False, }, - { - "use_local_cost_function": False, - "use_overlap_test": True - }, + {"use_local_cost_function": False, "use_overlap_test": True}, ) self.estimators = ( @@ -61,43 +56,42 @@ def setUp(self): self.samplers = ( Sampler(), - BackendSampler(BasicAer.get_backend("qasm_simulator")) + BackendSampler(BasicAer.get_backend("qasm_simulator")), ) - self.log = VQLSLog([],[]) - + self.log = VQLSLog([], []) def test_numpy_input(self): """Test the VQLS on matrix input using statevector simulator.""" - - matrix = np.array([ [0.50, 0.25, 0.10, 0.00], - [0.25, 0.50, 0.25, 0.10], - [0.10, 0.25, 0.50, 0.25], - [0.00, 0.10, 0.25, 0.50] ]) - rhs = np.array([0.1]*4) - ansatz = RealAmplitudes(num_qubits=2, reps=3, entanglement='full') + matrix = np.array( + [ + [0.50, 0.25, 0.10, 0.00], + [0.25, 0.50, 0.25, 0.10], + [0.10, 0.25, 0.50, 0.25], + [0.00, 0.10, 0.25, 0.50], + ] + ) - - for estimator, sampler in zip(self.estimators, self.samplers): - for opt in self.options: + rhs = np.array([0.1] * 4) + ansatz = RealAmplitudes(num_qubits=2, reps=3, entanglement="full") + for estimator, sampler in zip(self.estimators, self.samplers): + for opt in self.options: vqls = VQLS( estimator, ansatz, COBYLA(maxiter=2, disp=True), callback=self.log.update, - sampler=sampler + sampler=sampler, ) _ = vqls.solve(matrix, rhs, opt) - - def test_circuit_input_statevector(self): """Test the VQLS on circuits input using statevector simulator.""" num_qubits = 2 - ansatz = RealAmplitudes(num_qubits=num_qubits, reps=3, entanglement='full') + ansatz = RealAmplitudes(num_qubits=num_qubits, reps=3, entanglement="full") rhs = QuantumCircuit(num_qubits) rhs.h(0) @@ -106,30 +100,26 @@ def test_circuit_input_statevector(self): qc1 = QuantumCircuit(num_qubits) qc1.x(0) qc1.x(1) - qc1.cnot(0,1) + qc1.cnot(0, 1) qc2 = QuantumCircuit(num_qubits) qc2.h(0) qc2.x(1) - qc2.cnot(0,1) + qc2.cnot(0, 1) - matrix = SymmetricDecomposition( - circuits = [qc1, qc2], - coefficients = [0.5, 0.5] - ) + matrix = SymmetricDecomposition(circuits=[qc1, qc2], coefficients=[0.5, 0.5]) - for estimator, sampler in zip(self.estimators, self.samplers): + for estimator, sampler in zip(self.estimators, self.samplers): for opt in self.options: vqls = VQLS( estimator, ansatz, COBYLA(maxiter=2, disp=True), sampler=sampler, - callback=self.log.update + callback=self.log.update, ) _ = vqls.solve([[0.5, qc1], [0.5, qc2]], rhs, opt) - if __name__ == "__main__": unittest.main() diff --git a/vqls_prototype/__init__.py b/vqls_prototype/__init__.py index 60801b9..e5a5ccd 100644 --- a/vqls_prototype/__init__.py +++ b/vqls_prototype/__init__.py @@ -22,9 +22,8 @@ __all__ = [ "VQLS", - "VQLSLog" - "HadammardTest", + "VQLSLog" "HadammardTest", "HadammardOverlapTest", "SymmetricDecomposition", - "PauliDecomposition" + "PauliDecomposition", ] From aebb2d8814c6ace6192cd5d262a8c526b5b29055 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 14:05:23 +0200 Subject: [PATCH 03/25] reformat ipynb --- .../01_how_to_solve_linear_system.ipynb | 26 ++++++------ docs/how_tos/02_how_to_use_circuits.ipynb | 17 +++----- docs/how_tos/03_how_to_use_runtime.ipynb | 16 +++---- docs/how_tos/04_how_to_control_options.ipynb | 42 +++++++++++-------- docs/tutorials/vqls.ipynb | 24 +++++------ docs/tutorials/vqls_runtime.ipynb | 12 ++---- 6 files changed, 63 insertions(+), 74 deletions(-) diff --git a/docs/how_tos/01_how_to_solve_linear_system.ipynb b/docs/how_tos/01_how_to_solve_linear_system.ipynb index e41e92a..086d653 100644 --- a/docs/how_tos/01_how_to_solve_linear_system.ipynb +++ b/docs/how_tos/01_how_to_solve_linear_system.ipynb @@ -35,7 +35,7 @@ "size = 4\n", "\n", "# matrix of the linear system\n", - "A = np.random.rand(size,size)\n", + "A = np.random.rand(size, size)\n", "A = A + A.T\n", "\n", "# right hand side of the linear system\n", @@ -77,9 +77,10 @@ ], "source": [ "from qiskit.circuit.library.n_local.real_amplitudes import RealAmplitudes\n", + "\n", "nqbit = int(np.log2(size))\n", "ansatz = RealAmplitudes(nqbit, entanglement=\"full\", reps=3, insert_barriers=False)\n", - "ansatz.decompose().draw('mpl')" + "ansatz.decompose().draw(\"mpl\")" ] }, { @@ -101,22 +102,17 @@ "outputs": [], "source": [ "from vqls_prototype import VQLS, VQLSLog\n", - "from qiskit.primitives import Estimator \n", + "from qiskit.primitives import Estimator\n", "from qiskit.algorithms import optimizers as opt\n", "\n", "# instantiate an estimator primitive\n", "estimator = Estimator()\n", "\n", - "# create a logger \n", - "log = VQLSLog([],[])\n", + "# create a logger\n", + "log = VQLSLog([], [])\n", "\n", "# create the vqls solver\n", - "vqls = VQLS(\n", - " estimator,\n", - " ansatz,\n", - " opt.CG(maxiter=200),\n", - " callback=log.update \n", - ")" + "vqls = VQLS(estimator, ansatz, opt.CG(maxiter=200), callback=log.update)" ] }, { @@ -188,9 +184,10 @@ ], "source": [ "import matplotlib.pyplot as plt\n", + "\n", "plt.semilogy(log.values)\n", - "plt.ylabel('Cost Function')\n", - "plt.xlabel('Iterations')" + "plt.ylabel(\"Cost Function\")\n", + "plt.xlabel(\"Iterations\")" ] }, { @@ -212,6 +209,7 @@ "outputs": [], "source": [ "from qiskit.quantum_info import Statevector\n", + "\n", "vqls_solution = np.real(Statevector(res.state).data)" ] }, @@ -252,7 +250,7 @@ } ], "source": [ - "ref_solution = np.linalg.solve(A, b/np.linalg.norm(b))\n", + "ref_solution = np.linalg.solve(A, b / np.linalg.norm(b))\n", "ref_solution = ref_solution / np.linalg.norm(ref_solution)\n", "\n", "plt.scatter(ref_solution, vqls_solution)\n", diff --git a/docs/how_tos/02_how_to_use_circuits.ipynb b/docs/how_tos/02_how_to_use_circuits.ipynb index 92a34fc..11ea8cc 100644 --- a/docs/how_tos/02_how_to_use_circuits.ipynb +++ b/docs/how_tos/02_how_to_use_circuits.ipynb @@ -61,13 +61,13 @@ "qc1 = QuantumCircuit(nqbit)\n", "qc1.x(0)\n", "qc1.x(1)\n", - "qc1.cnot(0,1)\n", + "qc1.cnot(0, 1)\n", "\n", "# second quantum circuit for A\n", "qc2 = QuantumCircuit(nqbit)\n", "qc2.h(0)\n", "qc2.x(1)\n", - "qc2.cnot(0,1)\n", + "qc2.cnot(0, 1)\n", "\n", "# quantum circuit for b\n", "rhs = QuantumCircuit(nqbit)\n", @@ -93,7 +93,7 @@ "outputs": [], "source": [ "from vqls_prototype import VQLS, VQLSLog\n", - "from qiskit.primitives import Estimator \n", + "from qiskit.primitives import Estimator\n", "from qiskit.algorithms import optimizers as opt\n", "from qiskit.circuit.library.n_local.real_amplitudes import RealAmplitudes\n", "\n", @@ -103,16 +103,11 @@ "# instantiate an estimator primitive\n", "estimator = Estimator()\n", "\n", - "# create a logger \n", - "log = VQLSLog([],[])\n", + "# create a logger\n", + "log = VQLSLog([], [])\n", "\n", "# create the vqls solver\n", - "vqls = VQLS(\n", - " estimator,\n", - " ansatz,\n", - " opt.CG(maxiter=200),\n", - " callback=log.update \n", - ")" + "vqls = VQLS(estimator, ansatz, opt.CG(maxiter=200), callback=log.update)" ] }, { diff --git a/docs/how_tos/03_how_to_use_runtime.ipynb b/docs/how_tos/03_how_to_use_runtime.ipynb index e3f813e..3b6743a 100644 --- a/docs/how_tos/03_how_to_use_runtime.ipynb +++ b/docs/how_tos/03_how_to_use_runtime.ipynb @@ -37,7 +37,7 @@ "nqbit = int(np.log2(size))\n", "\n", "# matrix of the linear system\n", - "A = np.random.rand(size,size)\n", + "A = np.random.rand(size, size)\n", "A = A + A.T\n", "\n", "# right hand side of the linear system\n", @@ -75,27 +75,21 @@ "\n", "# start session\n", "with Session(service=service, backend=backend) as session:\n", - "\n", " # options of the primitives\n", " options = Options()\n", " options.optimization_level = 3\n", "\n", - " # estimator \n", + " # estimator\n", " estimator = Estimator(session=session, options=options)\n", "\n", " # log\n", - " log = VQLSLog([],[]) \n", + " log = VQLSLog([], [])\n", "\n", " # declare the solver\n", - " vqls = VQLS(\n", - " estimator,\n", - " ansatz,\n", - " optimizer=opt.CG(maxiter=200),\n", - " callback=log.update\n", - " )\n", + " vqls = VQLS(estimator, ansatz, optimizer=opt.CG(maxiter=200), callback=log.update)\n", "\n", " # solve the linear system\n", - " solution = vqls.solve(A, b)\n" + " solution = vqls.solve(A, b)" ] } ], diff --git a/docs/how_tos/04_how_to_control_options.ipynb b/docs/how_tos/04_how_to_control_options.ipynb index f1a1044..c660c19 100644 --- a/docs/how_tos/04_how_to_control_options.ipynb +++ b/docs/how_tos/04_how_to_control_options.ipynb @@ -39,7 +39,7 @@ "nqbit = int(np.log2(size))\n", "\n", "# matrix of the linear system\n", - "A = np.random.rand(size,size)\n", + "A = np.random.rand(size, size)\n", "A = A + A.T\n", "\n", "# right hand side of the linear system\n", @@ -61,10 +61,12 @@ "from qiskit.algorithms import optimizers as opt\n", "\n", "# instantiate an estimator primitive\n", - "estimator, sampler, log = Estimator(), Sampler(), VQLSLog([],[])\n", + "estimator, sampler, log = Estimator(), Sampler(), VQLSLog([], [])\n", "\n", "# create the vqls solver\n", - "vqls = VQLS(estimator,ansatz,opt.CG(maxiter=200),callback=log.update,sampler=sampler)" + "vqls = VQLS(\n", + " estimator, ansatz, opt.CG(maxiter=200), callback=log.update, sampler=sampler\n", + ")" ] }, { @@ -85,9 +87,11 @@ "metadata": {}, "outputs": [], "source": [ - "opt= {\"use_overlap_test\": ... ,\n", - " \"use_local_cost_function\": ...,\n", - " \"matrix_decomposition\": ... }" + "opt = {\n", + " \"use_overlap_test\": ...,\n", + " \"use_local_cost_function\": ...,\n", + " \"matrix_decomposition\": ...,\n", + "}" ] }, { @@ -137,9 +141,10 @@ } ], "source": [ - "from vqls_prototype import PauliDecomposition \n", + "from vqls_prototype import PauliDecomposition\n", + "\n", "pauli_decomposition = PauliDecomposition(A)\n", - "pauli_decomposition.circuits[5].draw('mpl')" + "pauli_decomposition.circuits[5].draw(\"mpl\")" ] }, { @@ -185,9 +190,10 @@ } ], "source": [ - "from vqls_prototype import SymmetricDecomposition \n", + "from vqls_prototype import SymmetricDecomposition\n", + "\n", "symmetric_decomposition = SymmetricDecomposition(A)\n", - "symmetric_decomposition.circuits[0].decompose().draw('mpl')" + "symmetric_decomposition.circuits[0].decompose().draw(\"mpl\")" ] }, { @@ -247,9 +253,9 @@ } ], "source": [ - "options = vqls._validate_solve_options({\"use_overlap_test\":False})\n", + "options = vqls._validate_solve_options({\"use_overlap_test\": False})\n", "_, qc_test = vqls.construct_circuit(A, b, options)\n", - "qc_test[0].circuits[0].decompose().draw('mpl')" + "qc_test[0].circuits[0].decompose().draw(\"mpl\")" ] }, { @@ -283,9 +289,9 @@ } ], "source": [ - "options = vqls._validate_solve_options({\"use_overlap_test\":True})\n", + "options = vqls._validate_solve_options({\"use_overlap_test\": True})\n", "_, qc_test = vqls.construct_circuit(A, b, options)\n", - "qc_test[0].circuits[0].decompose().draw('mpl')" + "qc_test[0].circuits[0].decompose().draw(\"mpl\")" ] }, { @@ -334,9 +340,9 @@ } ], "source": [ - "options = vqls._validate_solve_options({\"use_local_cost_function\":False})\n", + "options = vqls._validate_solve_options({\"use_local_cost_function\": False})\n", "_, qc_test = vqls.construct_circuit(A, b, options)\n", - "qc_test[0].circuits[0].decompose().draw('mpl')" + "qc_test[0].circuits[0].decompose().draw(\"mpl\")" ] }, { @@ -370,9 +376,9 @@ } ], "source": [ - "options = vqls._validate_solve_options({\"use_local_cost_function\":True})\n", + "options = vqls._validate_solve_options({\"use_local_cost_function\": True})\n", "_, qc_test = vqls.construct_circuit(A, b, options)\n", - "qc_test[0].circuits[0].decompose().draw('mpl')" + "qc_test[0].circuits[0].decompose().draw(\"mpl\")" ] }, { diff --git a/docs/tutorials/vqls.ipynb b/docs/tutorials/vqls.ipynb index f5b7a8d..bd58643 100644 --- a/docs/tutorials/vqls.ipynb +++ b/docs/tutorials/vqls.ipynb @@ -7,7 +7,7 @@ "outputs": [], "source": [ "from vqls_prototype import VQLS, VQLSLog\n", - "from qiskit.primitives import Estimator, Sampler \n", + "from qiskit.primitives import Estimator, Sampler\n", "from qiskit.circuit.library.n_local.real_amplitudes import RealAmplitudes\n", "from qiskit.algorithms.optimizers import COBYLA\n", "import numpy as np" @@ -103,6 +103,7 @@ ], "source": [ "from qiskit.algorithms.linear_solvers.numpy_linear_solver import NumPyLinearSolver\n", + "\n", "classical_solution = NumPyLinearSolver().solve(A, b / np.linalg.norm(b))" ] }, @@ -138,7 +139,7 @@ "metadata": {}, "outputs": [], "source": [ - "log = VQLSLog([],[])\n", + "log = VQLSLog([], [])\n", "estimator = Estimator()\n", "sampler = Sampler()\n", "vqls = VQLS(\n", @@ -146,7 +147,7 @@ " ansatz,\n", " COBYLA(maxiter=250, disp=True),\n", " sampler=sampler,\n", - " callback=log.update \n", + " callback=log.update,\n", ")" ] }, @@ -169,8 +170,7 @@ } ], "source": [ - "opt= {\"use_overlap_test\": False,\n", - " \"use_local_cost_function\": False}\n", + "opt = {\"use_overlap_test\": False, \"use_local_cost_function\": False}\n", "res = vqls.solve(A, b, opt)" ] }, @@ -289,15 +289,15 @@ "source": [ "colors = log.values[:-1]\n", "colors /= np.max(colors)\n", - "for img in range(1,50):\n", + "for img in range(1, 50):\n", " plt.cla()\n", - " for c, s in zip(colors[:img-1], solutions[:img-1]):\n", - " plt.scatter(ref_solution, -s, c=[c]*4, cmap='jet', s=10*(1-c), alpha=0.1)\n", - " plt.scatter(ref_solution, -solutions[img], s=50, edgecolors='white', c ='black')\n", - " plt.plot([-1, 1], [-1, 1], \"--\", c='grey')\n", + " for c, s in zip(colors[: img - 1], solutions[: img - 1]):\n", + " plt.scatter(ref_solution, -s, c=[c] * 4, cmap=\"jet\", s=10 * (1 - c), alpha=0.1)\n", + " plt.scatter(ref_solution, -solutions[img], s=50, edgecolors=\"white\", c=\"black\")\n", + " plt.plot([-1, 1], [-1, 1], \"--\", c=\"grey\")\n", " plt.grid()\n", - " plt.xlabel('True Solution')\n", - " plt.ylabel('VQLS Solution')\n", + " plt.xlabel(\"True Solution\")\n", + " plt.ylabel(\"VQLS Solution\")\n", " # img_name = \"./image/image_%03d.png\" %img\n", " # plt.savefig(img_name)" ] diff --git a/docs/tutorials/vqls_runtime.ipynb b/docs/tutorials/vqls_runtime.ipynb index 7826556..716b1e9 100644 --- a/docs/tutorials/vqls_runtime.ipynb +++ b/docs/tutorials/vqls_runtime.ipynb @@ -90,6 +90,7 @@ "outputs": [], "source": [ "from qiskit.algorithms.linear_solvers.numpy_linear_solver import NumPyLinearSolver\n", + "\n", "classical_solution = NumPyLinearSolver().solve(A, b / np.linalg.norm(b))" ] }, @@ -127,7 +128,7 @@ "source": [ "# define the runtime\n", "service = QiskitRuntimeService()\n", - "backend = \"simulator_statevector\"" + "backend = \"simulator_statevector\"" ] }, { @@ -147,13 +148,8 @@ "with Session(service=service, backend=backend) as session:\n", " options = Options()\n", " estimator = Estimator(session=session, options=options)\n", - " log = VQLSLog([],[])\n", - " vqls = VQLS(\n", - " estimator,\n", - " ansatz,\n", - " COBYLA(maxiter=250, disp=True),\n", - " callback=log.update \n", - " )\n", + " log = VQLSLog([], [])\n", + " vqls = VQLS(estimator, ansatz, COBYLA(maxiter=250, disp=True), callback=log.update)\n", "\n", " res = vqls.solve(A, b)" ] From 84e9eeb828b4779bbf755a138d59ae1fbc1c58a6 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 15:05:10 +0200 Subject: [PATCH 04/25] fix pylint --- tests/test_decomposition.py | 15 +++++++++++ tests/test_vqls.py | 9 +------ tox.ini | 4 +-- vqls_prototype/__init__.py | 3 ++- vqls_prototype/matrix_decomposition.py | 35 ++++++++++++++++---------- 5 files changed, 42 insertions(+), 24 deletions(-) diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index fd754e7..2a9ba78 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -1,3 +1,15 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + import numpy as np from numpy.testing import assert_allclose import pytest @@ -11,6 +23,7 @@ @pytest.fixture(params=[2, 4, 8, 16]) def symmetric(request): + """Generate a symmetric matrix""" dim = request.param mat = np.random.rand(dim, dim) mat = mat + mat.T @@ -18,6 +31,7 @@ def symmetric(request): def test_decomposition_raises(): + """Test error raised""" mat = np.eye(4)[-1::-1] with pytest.raises(NotImplementedError, match="decompose.+MatrixDecomposition"): MatrixDecomposition(matrix=mat) @@ -27,5 +41,6 @@ def test_decomposition_raises(): "decomposition_t", [SymmetricDecomposition, PauliDecomposition] ) def test_decomposition(symmetric, decomposition_t): + """Test decompositions""" decomp = decomposition_t(matrix=symmetric) assert_allclose(decomp.recompose(), symmetric) diff --git a/tests/test_vqls.py b/tests/test_vqls.py index bc2e605..2fe1386 100644 --- a/tests/test_vqls.py +++ b/tests/test_vqls.py @@ -20,17 +20,12 @@ from qiskit import BasicAer, QuantumCircuit from qiskit.circuit.library import RealAmplitudes -from qiskit.utils import algorithm_globals, has_aer -from qiskit.circuit.library.n_local.real_amplitudes import RealAmplitudes -from vqls_prototype import SymmetricDecomposition +from qiskit.utils import algorithm_globals from qiskit.algorithms.optimizers import COBYLA from qiskit.primitives import Estimator, Sampler, BackendEstimator, BackendSampler from vqls_prototype import VQLS, VQLSLog -if has_aer(): - from qiskit import Aer - class TestVQLS(QiskitTestCase): """Test VQLS""" @@ -107,8 +102,6 @@ def test_circuit_input_statevector(self): qc2.x(1) qc2.cnot(0, 1) - matrix = SymmetricDecomposition(circuits=[qc1, qc2], coefficients=[0.5, 0.5]) - for estimator, sampler in zip(self.estimators, self.samplers): for opt in self.options: vqls = VQLS( diff --git a/tox.ini b/tox.ini index bab018b..6ad91bd 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ envdir = .tox/lint skip_install = true commands = black --check . - pylint -rn prototype_template tests + pylint -rn vqls_prototype tests nbqa pylint -rn docs/ mypy . @@ -38,7 +38,7 @@ basepython = python3 setenv = {[testenv]setenv} commands = - coverage3 run --source prototype_template --parallel-mode -m pytest --doctest-modules + coverage3 run --source vqls_prototype --parallel-mode -m pytest --doctest-modules coverage3 combine coverage3 report --fail-under=80 diff --git a/vqls_prototype/__init__.py b/vqls_prototype/__init__.py index e5a5ccd..e6cf8a8 100644 --- a/vqls_prototype/__init__.py +++ b/vqls_prototype/__init__.py @@ -22,7 +22,8 @@ __all__ = [ "VQLS", - "VQLSLog" "HadammardTest", + "VQLSLog", + "HadammardTest", "HadammardOverlapTest", "SymmetricDecomposition", "PauliDecomposition", diff --git a/vqls_prototype/matrix_decomposition.py b/vqls_prototype/matrix_decomposition.py index 0f04cda..8e24cbf 100644 --- a/vqls_prototype/matrix_decomposition.py +++ b/vqls_prototype/matrix_decomposition.py @@ -1,3 +1,4 @@ +"""Methods to decompose a matrix into quantum circuits""" from collections import namedtuple from itertools import product from typing import Optional, Union, List, Tuple, TypeVar, cast @@ -46,11 +47,14 @@ def __init__( """Decompose a matrix representing quantum circuits Args: - matrix (Optional[npt.NDArray], optional): Array to decompose; only relevant in derived classes where - `self.decompose_matrix()` has been implemented. Defaults to None. - circuits (Optional[Union[QuantumCircuit, List[QuantumCircuit]]], optional): quantum circuits representing the matrix. Defaults to None. - coefficients (Optional[ Union[float, complex, List[float], List[complex]] ], optional): coefficients associated with the input quantum circuits; `None` is - valid only for a circuit with 1 element. Defaults to None. + matrix (Optional[npt.NDArray], optional): Array to decompose; + only relevant in derived classes where + `self.decompose_matrix()` has been implemented. Defaults to None. + circuits (Optional[Union[QuantumCircuit, List[QuantumCircuit]]], optional): + quantum circuits representing the matrix. Defaults to None. + coefficients (Optional[ Union[float, complex, List[float], List[complex]] ], optional): + coefficients associated with the input quantum circuits; `None` is + valid only for a circuit with 1 element. Defaults to None. """ if matrix is not None: # ignore circuits & coefficients @@ -85,7 +89,8 @@ def __init__( self._matrix = self.recompose() else: raise ValueError( - f"inconsistent arguments: matrix={matrix}, coefficients={coefficients}, circuits={circuits}" + f"inconsistent arguments: matrix={matrix}, \ + coefficients={coefficients}, circuits={circuits}" ) self.num_circuits = len(self._circuits) @@ -207,9 +212,9 @@ def _create_circuits( """ def make_qc(mat: complex_arr_t, name: str) -> QuantumCircuit: - qc = QuantumCircuit(self.num_qubits, name=name) - qc.unitary(mat, qc.qubits) - return qc + circuit = QuantumCircuit(self.num_qubits, name=name) + circuit.unitary(mat, circuit.qubits) + return circuit return [make_qc(mat, name) for mat, name in zip(unimatrices, names)] @@ -217,7 +222,8 @@ def make_qc(mat: complex_arr_t, name: str) -> QuantumCircuit: def auxilliary_matrix( x: Union[npt.NDArray[np.float_], complex_arr_t] ) -> complex_arr_t: - """Returns the auxiliary matrix for the decomposition of size n and derfined as defined as : i * sqrt(I - x^2) + """Returns the auxiliary matrix for the decomposition of size n. + and derfined as defined as : i * sqrt(I - x^2) Args: x (Union[npt.NDArray[np.float_], complex_arr_t]): original matrix. @@ -235,7 +241,9 @@ def decompose_matrix( """Decompose a generic numpy matrix into a sum of unitary matrices. Returns: - Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: A tuple containing the list of coefficients numpy matrices, and quantum circuits of the decomposition. + Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + A tuple containing the list of coefficients numpy matrices, + and quantum circuits of the decomposition. """ # Normalize @@ -289,7 +297,7 @@ def _create_circuit(pauli_string: str) -> QuantumCircuit: if ( gate.upper() != "I" ): # identity gate cannot be controlled by ancillary qubit - qc.__getattribute__(gate.lower())(iqbit) + qc.getattr(gate.lower())(iqbit) return qc def decompose_matrix( @@ -299,7 +307,8 @@ def decompose_matrix( Returns: Tuple[complex_arr_t, List[complex_arr_t]]: - A tuple containing the list of coefficients and the numpy matrix of the decomposition. + A tuple containing the list of coefficients and + the numpy matrix of the decomposition. """ prefactor = 1.0 / (2**self.num_qubits) From cceefa53238a6074868821328a2515427a2767a1 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 15:47:30 +0200 Subject: [PATCH 05/25] lint --- docs/apidocs/index.rst | 4 +- vqls_prototype/hadamard_test.py | 158 +++++++++++--------- vqls_prototype/matrix_decomposition.py | 56 +++---- vqls_prototype/variational_linear_solver.py | 15 +- vqls_prototype/vqls.py | 85 ++++++----- 5 files changed, 180 insertions(+), 138 deletions(-) diff --git a/docs/apidocs/index.rst b/docs/apidocs/index.rst index e83a56b..7a332bc 100644 --- a/docs/apidocs/index.rst +++ b/docs/apidocs/index.rst @@ -1,6 +1,6 @@ .. vqls: -.. module:: vqls +.. module:: vqls_prototype ============================= Template API References @@ -9,4 +9,4 @@ Template API References .. toctree:: :maxdepth: 1 - vqls + vqls_prototype diff --git a/vqls_prototype/hadamard_test.py b/vqls_prototype/hadamard_test.py index b9646a1..8ce38b1 100644 --- a/vqls_prototype/hadamard_test.py +++ b/vqls_prototype/hadamard_test.py @@ -26,11 +26,16 @@ def __init__( \\langle \\Psi | U | \\Psi \\rangle Args: - operators (Union[QuantumCircuit, List[QuantumCircuit]]): quantum circuit or list of quantum circuits representing the U. - use_barrier (Optional[bool], optional): introduce barriers in the description of the circuits. Defaults to False. - apply_control_to_operator (Optional[bool], optional): Apply control operator to the input quantum circuits. Defaults to True. - apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create |Psi> from |0>. If None, assume that the qubits are alredy in Psi. - apply_measurement (Optional[bool], optional): apply explicit measurement. Defaults to False. + operators (Union[QuantumCircuit, List[QuantumCircuit]]): quantum circuit or + list of quantum circuits representing the U. + use_barrier (Optional[bool], optional): introduce barriers in the + description of the circuits. Defaults to False. + apply_control_to_operator (Optional[bool], optional): Apply control operator to the + input quantum circuits. Defaults to True. + apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create + |Psi> from |0>. If None, assume that the qubits are alredy in Psi. + apply_measurement (Optional[bool], optional): apply explicit measurement. + Defaults to False. """ @@ -45,14 +50,16 @@ def __init__( if apply_initial_state is not None: if apply_initial_state.num_qubits != operators[0].num_qubits: raise ValueError( - "The operator and the initial state circuits have different numbers of qubits" + "The operator and the initial state circuits \ + have different numbers of qubits" ) else: self.num_qubits = operators[0].num_qubits if apply_initial_state is not None: if apply_initial_state.num_qubits != operators[0].num_qubits - 1: raise ValueError( - "The operator and the initial state circuits have different numbers of qubits" + "The operator and the initial state circuits \ + have different numbers of qubits" ) # classical bit for explicit measurement @@ -87,11 +94,16 @@ def _build_circuit( """build the quantum circuits Args: - operators (List[QuantumCircuit]): quantum circuit or list of quantum circuits representing the U. + operators (List[QuantumCircuit]): quantum circuit or list of quantum circuits + representing the U. use_barrier (bool): introduce barriers in the description of the circuits. - apply_control_to_operator (bool): Apply control operator to the input quantum circuits. - apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create |Psi> from |0>. If None, assume that the qubits are alredy in Psi. Defaults to None. - apply_measurement (Optional[bool], optional): apply explicit measurement. Defaults to False. + apply_control_to_operator (bool): Apply control operator to the + input quantum circuits. + apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to + create |Psi> from |0>. If None, assume that the qubits are alredy in Psi. + Defaults to None. + apply_measurement (Optional[bool], optional): apply explicit measurement. + Defaults to False. Returns: List[QuantumCircuit]: List of quamtum circuits required to compute the Hadammard Test. @@ -100,43 +112,43 @@ def _build_circuit( for imaginary in [False, True]: if apply_measurement: - qc = QuantumCircuit(self.num_qubits, self.num_clbits) + circuit = QuantumCircuit(self.num_qubits, self.num_clbits) else: - qc = QuantumCircuit(self.num_qubits) + circuit = QuantumCircuit(self.num_qubits) if apply_initial_state is not None: - qc.append(apply_initial_state, list(range(1, self.num_qubits))) + circuit.append(apply_initial_state, list(range(1, self.num_qubits))) if use_barrier: - qc.barrier() + circuit.barrier() # hadadmard gate on ctrl qbit - qc.h(0) + circuit.h(0) # Sdg on ctrl qbit if imaginary: - qc.sdg(0) + circuit.sdg(0) if use_barrier: - qc.barrier() + circuit.barrier() # matrix circuit - for op, ctrl in zip(operators, apply_control_to_operator): + for operator, ctrl in zip(operators, apply_control_to_operator): if ctrl: - qc.append(op.control(1), list(range(0, self.num_qubits))) + circuit.append(operator.control(1), list(range(0, self.num_qubits))) else: - qc.append(op, list(range(0, self.num_qubits))) + circuit.append(operator, list(range(0, self.num_qubits))) if use_barrier: - qc.barrier() + circuit.barrier() # hadamard on ctrl circuit - qc.h(0) + circuit.h(0) # measure if apply_measurement: - qc.measure(0, 0) + circuit.measure(0, 0) - circuits.append(qc) + circuits.append(circuit) return circuits @@ -144,12 +156,15 @@ def _build_observable(self) -> List[TensoredOp]: """Create the operator to measure |1> on the control qubit. Returns: - Lis[TensoredOp]: List of two observables to measure |1> on the control qubit I^...^I^|1><1| + Lis[TensoredOp]: List of two observables to measure + |1> on the control qubit I^...^I^|1><1| """ - p0 = "I" * self.num_qubits - p1 = "I" * (self.num_qubits - 1) + "Z" - one_op_ctrl = SparsePauliOp([p0, p1], np.array([0.5 + 0.0j, -0.5 + 0.0j])) + proba_0 = "I" * self.num_qubits + proba_1 = "I" * (self.num_qubits - 1) + "Z" + one_op_ctrl = SparsePauliOp( + [proba_0, proba_1], np.array([0.5 + 0.0j, -0.5 + 0.0j]) + ) return one_op_ctrl def get_value(self, estimator, parameter_sets: List) -> List: @@ -192,10 +207,15 @@ def __init__( \\langle 0 | U^\dagger A_l V | 0 \\rangle \\langle V^\dagger A_m^\dagger U | 0 \\rangle Args: - operators (List[QuantumCircuit]): List of quantum circuits representing the operators [U, A_l, A_m]. - use_barrier (Optional[bool], optional): introduce barriers in the description of the circuits. Defaults to False. - apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create |Psi> from |0>. If None, assume that the qubits of the firsr register are alredy in Psi. - apply_measurement (Optional[bool], optional): apply explicit measurement. Defaults to False. + operators (List[QuantumCircuit]): List of quantum circuits representing + the operators [U, A_l, A_m]. + use_barrier (Optional[bool], optional): introduce barriers in the + description of the circuits. Defaults to False. + apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create + |Psi> from |0>. If None, assume that the qubits of the firsr + register are alredy in Psi. + apply_measurement (Optional[bool], optional): apply explicit measurement. + Defaults to False. Returns: List[QuantumCircuit]: List of quamtum circuits required to compute the Hadammard Test. @@ -239,69 +259,73 @@ def _build_circuit( """build the quantum circuits Args: - operators (List[QuantumCircuit]): quantum circuit or list of quantum circuits representing the [U, Al, Am]. + operators (List[QuantumCircuit]): quantum circuit or list of quantum circuits + representing the [U, Al, Am]. use_barrier (bool): introduce barriers in the description of the circuits. - apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create |Psi> from |0>. If None, assume that the qubits are alredy in Psi. Defaults to None. - apply_measurement (Optional[bool], optional): apply explicit measurement. Defaults to False. + apply_initial_state (Optional[QuantumCircuit], optional): Quantum Circuit to create + |Psi> from |0>. If None, assume that the qubits are alredy in Psi. + Defaults to None. + apply_measurement (Optional[bool], optional): apply explicit measurement. + Defaults to False. Returns: List[QuantumCircuit]: List of quamtum circuits required to compute the Hadammard Test. """ circuits = [] - U, Al, Am = operators + op_umat, op_al, op_am = operators for imaginary in [False, True]: qctrl = QuantumRegister(1, "qctrl") - qreg0 = QuantumRegister(Al.num_qubits, "qr0") - qreg1 = QuantumRegister(Am.num_qubits, "qr1") - qc = QuantumCircuit(qctrl, qreg0, qreg1) + qreg0 = QuantumRegister(op_al.num_qubits, "qr0") + qreg1 = QuantumRegister(op_am.num_qubits, "qr1") + circuit = QuantumCircuit(qctrl, qreg0, qreg1) # hadadmard gate on ctrl qbit - qc.h(qctrl) + circuit.h(qctrl) # prepare psi on the first register if apply_initial_state is not None: - qc.append(apply_initial_state, qreg0) + circuit.append(apply_initial_state, qreg0) # apply U on the second register - qc.append(U, qreg1) + circuit.append(op_umat, qreg1) if use_barrier: - qc.barrier() + circuit.barrier() # apply Al on the first qreg - idx = [0] + list(range(1, Al.num_qubits + 1)) - qc.append(Al.control(1), idx) + idx = [0] + list(range(1, op_al.num_qubits + 1)) + circuit.append(op_al.control(1), idx) # apply Am^\dagger on the second reg - idx = [0] + list(range(Al.num_qubits + 1, 2 * Al.num_qubits + 1)) - qc.append(Am.inverse().control(1), idx) + idx = [0] + list(range(op_al.num_qubits + 1, 2 * op_al.num_qubits + 1)) + circuit.append(op_am.inverse().control(1), idx) if use_barrier: - qc.barrier() + circuit.barrier() # apply the cnot gate - for q0, q1 in zip(qreg0, qreg1): - qc.cx(q0, q1) + for qubit_0, qubit_1 in zip(qreg0, qreg1): + circuit.cx(qubit_0, qubit_1) # Sdg on ctrl qbit if imaginary: - qc.rz(-np.pi / 2, qctrl) + circuit.rz(-np.pi / 2, qctrl) if use_barrier: - qc.barrier() + circuit.barrier() # hadamard on ctrl circuit - qc.h(qctrl) - for q0 in qreg0: - qc.h(q0) + circuit.h(qctrl) + for qubit_0 in qreg0: + circuit.h(qubit_0) # measure if apply_measurement: - qc.measure_all(inplace=True) + circuit.measure_all(inplace=True) - circuits.append(qc) + circuits.append(circuit) return circuits @@ -311,10 +335,10 @@ def compute_post_processing_coefficients(self): # compute [1,1,1,-1] \otimes n # these are the coefficients if the qubits of register A and B # are ordered as A0 B0 A1 B1 .... AN BN - c0 = np.array([1, 1, 1, -1]) + coeff_0 = np.array([1, 1, 1, -1]) coeffs = np.array([1, 1, 1, -1]) for _ in range(1, self.operator_num_qubits): - coeffs = np.tensordot(coeffs, c0, axes=0).flatten() + coeffs = np.tensordot(coeffs, coeff_0, axes=0).flatten() # create all the possible bit strings of a single register bit_strings = [] @@ -359,19 +383,17 @@ def post_processing(sampler_result) -> List: quasi_dist = sampler_result.quasi_dists output = [] - for qd in quasi_dist: + for qdist in quasi_dist: # add missing keys val = np.array( - [qd[k] if k in qd else 0 for k in range(2**self.num_qubits)] + [qdist[k] if k in qdist else 0 for k in range(2**self.num_qubits)] ) - # val = (val * val.conj()) - # v0, v1 = np.array_split(val, 2) - v0, v1 = val[0::2], val[1::2] - p0 = (v0 * self.post_process_coeffs).sum() - p1 = (v1 * self.post_process_coeffs).sum() + value_0, value_1 = val[0::2], val[1::2] + proba_0 = (value_0 * self.post_process_coeffs).sum() + proba_1 = (value_1 * self.post_process_coeffs).sum() - output.append(p0 - p1) + output.append(proba_0 - proba_1) return output diff --git a/vqls_prototype/matrix_decomposition.py b/vqls_prototype/matrix_decomposition.py index 8e24cbf..351fd06 100644 --- a/vqls_prototype/matrix_decomposition.py +++ b/vqls_prototype/matrix_decomposition.py @@ -12,8 +12,8 @@ from qiskit.quantum_info import Operator, Pauli -complex_t = TypeVar("complex_t", float, complex) -complex_arr_t = npt.NDArray[np.cdouble] +complex_number_type = TypeVar("complex_number_type", float, complex) +complex_array_type = npt.NDArray[np.cdouble] class MatrixDecomposition: @@ -23,15 +23,15 @@ class MatrixDecomposition: @classmethod def _as_complex( - cls, num_or_arr: Union[complex_t, List[complex_t]] - ) -> complex_arr_t: + cls, num_or_arr: Union[complex_number_type, List[complex_number_type]] + ) -> complex_array_type: """Converts a number or a list of numbers to a complex array. Args: - num_or_arr (Union[complex_t, List[complex_t]]): array of number to convert + num_or_arr (Union[complex_type, List[complex_number_type]]): array of number to convert Returns: - complex_arr_t: array of complex numbers + complex_array_type: array of complex numbers """ arr = num_or_arr if isinstance(num_or_arr, List) else [num_or_arr] return np.array(arr, dtype=np.cdouble) @@ -109,11 +109,13 @@ def _compute_circuit_size(cls, matrix: npt.NDArray) -> int: return int(np.log2(matrix.shape[0])) @classmethod - def _validate_matrix(cls, matrix: complex_arr_t) -> Tuple[complex_arr_t, int]: + def _validate_matrix( + cls, matrix: complex_array_type + ) -> Tuple[complex_array_type, int]: """Check the size of the matrix Args: - matrix (complex_arr_t): input matrix + matrix (complex_array_type): input matrix Raises: ValueError: if the matrix is not square @@ -121,7 +123,7 @@ def _validate_matrix(cls, matrix: complex_arr_t) -> Tuple[complex_arr_t, int]: ValueError: if the matrix is not symmetric Returns: - Tuple[complex_arr_t, int]: matrix and the number of qubits required + Tuple[complex_array_type, int]: matrix and the number of qubits required """ if len(matrix.shape) == 2 and matrix.shape[0] != matrix.shape[1]: raise ValueError( @@ -148,12 +150,12 @@ def circuits(self) -> List[QuantumCircuit]: return self._circuits @property - def coefficients(self) -> complex_arr_t: + def coefficients(self) -> complex_array_type: """coefficients of the decomposition.""" return self._coefficients @property - def matrices(self) -> List[complex_arr_t]: + def matrices(self) -> List[complex_array_type]: """return the unitary matrices""" return self._matrices @@ -176,18 +178,18 @@ def __len__(self): def __getitem__(self, index): return self.CircuitElement(self._coefficients[index], self._circuits[index]) - def recompose(self) -> complex_arr_t: + def recompose(self) -> complex_array_type: """Rebuilds the original matrix from the decomposed one. Returns: - complex_arr_t: The recomposed matrix. + complex_array_type: The recomposed matrix. """ coeffs, matrices = self.coefficients, self.matrices return (coeffs.reshape(len(coeffs), 1, 1) * matrices).sum(axis=0) def decompose_matrix( self, - ) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + ) -> Tuple[complex_array_type, List[complex_array_type], List[QuantumCircuit]]: raise NotImplementedError(f"can't decompose in {self.__class__.__name__!r}") @@ -211,7 +213,7 @@ def _create_circuits( List[QuantumCircuit]: quantum circuits """ - def make_qc(mat: complex_arr_t, name: str) -> QuantumCircuit: + def make_qc(mat: complex_array_type, name: str) -> QuantumCircuit: circuit = QuantumCircuit(self.num_qubits, name=name) circuit.unitary(mat, circuit.qubits) return circuit @@ -220,16 +222,16 @@ def make_qc(mat: complex_arr_t, name: str) -> QuantumCircuit: @staticmethod def auxilliary_matrix( - x: Union[npt.NDArray[np.float_], complex_arr_t] - ) -> complex_arr_t: + x: Union[npt.NDArray[np.float_], complex_array_type] + ) -> complex_array_type: """Returns the auxiliary matrix for the decomposition of size n. and derfined as defined as : i * sqrt(I - x^2) Args: - x (Union[npt.NDArray[np.float_], complex_arr_t]): original matrix. + x (Union[npt.NDArray[np.float_], complex_array_type]): original matrix. Returns: - complex_arr_t: The auxiliary matrix. + complex_array_type: The auxiliary matrix. """ mat = np.eye(len(x)) - x @ x mat = cast(npt.NDArray[Union[np.float_, np.cdouble]], spla.sqrtm(mat)) @@ -237,11 +239,11 @@ def auxilliary_matrix( def decompose_matrix( self, - ) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + ) -> Tuple[complex_array_type, List[complex_array_type], List[QuantumCircuit]]: """Decompose a generic numpy matrix into a sum of unitary matrices. Returns: - Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + Tuple[complex_array_type, List[complex_array_type], List[QuantumCircuit]]: A tuple containing the list of coefficients numpy matrices, and quantum circuits of the decomposition. """ @@ -292,21 +294,21 @@ def _create_circuit(pauli_string: str) -> QuantumCircuit: QuantumCircuit: quantum circuit for the string """ num_qubit = len(pauli_string) - qc = QuantumCircuit(num_qubit, name=pauli_string) + circuit = QuantumCircuit(num_qubit, name=pauli_string) for iqbit, gate in enumerate(pauli_string[::-1]): if ( gate.upper() != "I" ): # identity gate cannot be controlled by ancillary qubit - qc.getattr(gate.lower())(iqbit) - return qc + getattr(circuit, gate.lower())(iqbit) + return circuit def decompose_matrix( self, - ) -> Tuple[complex_arr_t, List[complex_arr_t], List[QuantumCircuit]]: + ) -> Tuple[complex_array_type, List[complex_array_type], List[QuantumCircuit]]: """Decompose a generic numpy matrix into a sum of Pauli strings. Returns: - Tuple[complex_arr_t, List[complex_arr_t]]: + Tuple[complex_array_type, List[complex_array_type]]: A tuple containing the list of coefficients and the numpy matrix of the decomposition. """ @@ -318,7 +320,7 @@ def decompose_matrix( pauli_string = "".join(pauli_gates) pauli_op = Pauli(pauli_string) pauli_matrix = pauli_op.to_matrix() - coef: complex_arr_t = np.trace(pauli_matrix @ self.matrix) + coef: complex_array_type = np.trace(pauli_matrix @ self.matrix) if coef * np.conj(coef) != 0: coeffs.append(prefactor * coef) diff --git a/vqls_prototype/variational_linear_solver.py b/vqls_prototype/variational_linear_solver.py index 0d6ae8c..f52c0c6 100644 --- a/vqls_prototype/variational_linear_solver.py +++ b/vqls_prototype/variational_linear_solver.py @@ -13,7 +13,7 @@ """An abstract class for variational linear systems solvers.""" from abc import ABC, abstractmethod -from typing import Union, Optional +from typing import Union, Optional, Dict import numpy as np from qiskit import QuantumCircuit @@ -23,8 +23,9 @@ class VariationalLinearSolverResult(VariationalResult): """A base class for linear systems results using variational methods - The linear systems variational algorithms return an object of the type ``VariationalLinearSystemsResult`` - with the information about the solution obtained. + The linear systems variational algorithms return an object of the type + ``VariationalLinearSystemsResult`` with the information about the + solution obtained. """ def __init__(self) -> None: @@ -42,12 +43,14 @@ def cost_function_evals(self, value: int) -> None: @property def state(self) -> Union[QuantumCircuit, np.ndarray]: - """return either the circuit that prepares the solution or the solution as a vector""" + """return either the circuit that prepares the solution or the solution + as a vector""" return self._state @state.setter def state(self, state: Union[QuantumCircuit, np.ndarray]) -> None: - """Set the solution state as either the circuit that prepares it or as a vector. + """Set the solution state as either the circuit that prepares + it or as a vector. Args: state: The new solution state. @@ -63,7 +66,7 @@ def solve( self, matrix: Union[np.ndarray, QuantumCircuit], vector: Union[np.ndarray, QuantumCircuit], - **kwargs + options: Union[Dict, None] = None, ) -> VariationalLinearSolverResult: """Solve the system and compute the observable(s) diff --git a/vqls_prototype/vqls.py b/vqls_prototype/vqls.py index b7321ca..af6881a 100644 --- a/vqls_prototype/vqls.py +++ b/vqls_prototype/vqls.py @@ -119,8 +119,8 @@ class VQLS(VariationalAlgorithm, VariationalLinearSolver): References: - [1] Carlos Bravo-Prieto, Ryan LaRose, M. Cerezo, Yigit Subasi, Lukasz Cincio, Patrick J. Coles - Variational Quantum Linear Solver + [1] Carlos Bravo-Prieto, Ryan LaRose, M. Cerezo, Yigit Subasi, Lukasz Cincio, + Patrick J. Coles. Variational Quantum Linear Solver `arXiv:1909.05820 ` """ @@ -158,7 +158,7 @@ def __init__( callback: a callback that can access the intermediate data during the optimization. Three parameter values are passed to the callback as follows during each evaluation by the optimizer for its current set of parameters as it works towards the minimum. - These are: the evaluation count, the cost and the optimizer parameters for the ansatz + These are: the evaluation count, the cost and the parameters for the ansatz """ super().__init__() @@ -295,7 +295,8 @@ def construct_circuit( Args: matrix (Union[np.ndarray, QuantumCircuit, List]): matrix of the linear system vector (Union[np.ndarray, QuantumCircuit]): rhs of thge linear system - options (Dict): Options to compute define the quantum circuits that compute the cost function + options (Dict): Options to compute define the quantum circuits + that compute the cost function Raises: ValueError: if vector and matrix have different size @@ -308,7 +309,7 @@ def construct_circuit( # state preparation if isinstance(vector, QuantumCircuit): - nb = vector.num_qubits + nqbit = vector.num_qubits self.vector_circuit = vector elif isinstance(vector, np.ndarray): @@ -316,8 +317,8 @@ def construct_circuit( vector = vector.astype("float64") # create the circuit - nb = int(np.log2(len(vector))) - self.vector_circuit = QuantumCircuit(nb, name="Ub") + nqbit = int(np.log2(len(vector))) + self.vector_circuit = QuantumCircuit(nqbit, name="Ub") # prep the vector if its norm is non nul vec_norm = np.linalg.norm(vector) @@ -386,14 +387,14 @@ def _get_norm_circuits(self) -> List[QuantumCircuit]: hdmr_tests_norm = [] - for ii in range(len(self.matrix_circuits)): - mi = self.matrix_circuits[ii] + for ii_mat in range(len(self.matrix_circuits)): + mat_i = self.matrix_circuits[ii_mat] - for jj in range(ii + 1, len(self.matrix_circuits)): - mj = self.matrix_circuits[jj] + for jj_mat in range(ii_mat + 1, len(self.matrix_circuits)): + mat_j = self.matrix_circuits[jj_mat] hdmr_tests_norm.append( HadammardTest( - operators=[mi.circuit.inverse(), mj.circuit], + operators=[mat_i.circuit.inverse(), mat_j.circuit], apply_initial_state=self._ansatz, apply_measurement=False, ) @@ -411,26 +412,26 @@ def _get_local_circuits(self) -> List[QuantumCircuit]: num_z = self.matrix_circuits[0].circuit.num_qubits # create the circuits for <0| U^* A_l V(Zj . Ij|) V^* Am^* U|0> - for ii in range(len(self.matrix_circuits)): - mi = self.matrix_circuits[ii] + for ii_mat in range(len(self.matrix_circuits)): + mat_i = self.matrix_circuits[ii_mat] - for jj in range(ii, len(self.matrix_circuits)): - mj = self.matrix_circuits[jj] + for jj_mat in range(ii_mat, len(self.matrix_circuits)): + mat_j = self.matrix_circuits[jj_mat] - for iq in range(num_z): + for iqubit in range(num_z): # circuit for the CZ operation on the iqth qubit qc_z = QuantumCircuit(num_z + 1) - qc_z.cz(0, iq + 1) + qc_z.cz(0, iqubit + 1) # create Hadammard circuit hdmr_tests_overlap.append( HadammardTest( operators=[ - mi.circuit, + mat_i.circuit, self.vector_circuit.inverse(), qc_z, self.vector_circuit, - mj.circuit.inverse(), + mat_j.circuit.inverse(), ], apply_control_to_operator=[True, True, False, True, True], apply_initial_state=self.ansatz, @@ -443,7 +444,8 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: """construct circuits needed for the global cost function Args: - options (Dict): Options to define the quantum circuits that compute the cost function + options (Dict): Options to define the quantum circuits that compute + the cost function Returns: List[QuantumCircuit]: quantum circuits needed for the global cost function @@ -453,26 +455,30 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: # create the circuits for <0|U^* A_l V|0\rangle\langle 0| V^* Am^* U|0> # either using overal test or hadammard test if options["use_overlap_test"]: - for ii in range(len(self.matrix_circuits)): - mi = self.matrix_circuits[ii] + for ii_mat in range(len(self.matrix_circuits)): + mat_i = self.matrix_circuits[ii_mat] - for jj in range(ii, len(self.matrix_circuits)): - mj = self.matrix_circuits[jj] + for jj_mat in range(ii_mat, len(self.matrix_circuits)): + mat_j = self.matrix_circuits[jj_mat] hdmr_tests_overlap.append( HadammardOverlapTest( - operators=[self.vector_circuit, mi.circuit, mj.circuit], + operators=[ + self.vector_circuit, + mat_i.circuit, + mat_j.circuit, + ], apply_initial_state=self.ansatz, apply_measurement=True, ) ) else: - for mi in self.matrix_circuits: + for mat_i in self.matrix_circuits: hdmr_tests_overlap.append( HadammardTest( operators=[ self.ansatz, - mi.circuit, + mat_i.circuit, self.vector_circuit.inverse(), ], apply_measurement=False, @@ -574,7 +580,13 @@ def _compute_global_terms( """Compute ||^2 .. math:: - |\\langle b|\\Phi\\rangle|^2 = \\sum_{nm} c_n^*c_m \\langle 0|V^* U_n^* U_b |0 \\rangle \\langle 0|U_b^* U_m V |0\\rangle + |\\langle b|\\Phi\\rangle|^2 = \\sum_{nm} c_n^*c_m \\gamma_{nm} + + with + + .. math:: + + \\gamma_nm = \\langle 0|V^* U_n^* U_b |0 \\rangle \\langle 0|U_b^* U_m V |0\\rangle Args: coeff_matrix (np.ndarray): the matrix values of the c_n^* c_m coefficients @@ -628,7 +640,8 @@ def _compute_local_terms( float: value of the sum """ - # add all the hadamard test values corresponding to the insertion of Z gates on the same cicuit + # add all the hadamard test values corresponding to the insertion + # of Z gates on the same cicuit # b_ij = \sum_n \\frac{1}{n} \\sum_n \\langle 0|V^* A_i U Z_n U^* A_j^* V|0\\rangle num_zgate = self.matrix_circuits[0].circuit.num_qubits hdmr_values = hdmr_values.reshape(-1, num_zgate).mean(1) @@ -740,11 +753,11 @@ def _validate_solve_options(self, options: Union[Dict, None]) -> Dict: else: for k in options.keys(): - if k not in self.default_solve_options.keys(): + if k not in valid_keys: raise ValueError( "Option {k} not recognized, valid keys are {valid_keys}" ) - for k in self.default_solve_options.keys(): + for k in valid_keys: if k not in options.keys(): options[k] = self.default_solve_options[k] @@ -761,7 +774,8 @@ def _validate_solve_options(self, options: Union[Dict, None]) -> Dict: valid_matrix_decomposition = ["symmetric", "pauli"] if options["matrix_decomposition"].lower() not in valid_matrix_decomposition: raise ValueError( - "matrix decomposition {k} not recognized, valid keys are {valid_matrix_decomposition}" + "matrix decomposition {k} not recognized, \ + valid keys are {valid_matrix_decomposition}" ) return options @@ -780,7 +794,8 @@ def solve( options (Union[Dict, None]): options for the calculation of the cost function Returns: - VariationalLinearSolverResult: Result of the optimization and solution vector of the linear system + VariationalLinearSolverResult: Result of the optimization + and solution vector of the linear system """ # validate the options @@ -793,7 +808,7 @@ def solve( # compute he coefficient matrix coefficient_matrix = self.get_coefficient_matrix( - np.array([mi.coeff for mi in self.matrix_circuits]) + np.array([mat_i.coeff for mat_i in self.matrix_circuits]) ) # set an expectation for this algorithm run (will be reset to None at the end) From d7ac42e4e0b1ca7a5eaf46bc39b4d1a97453776a Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 15:58:36 +0200 Subject: [PATCH 06/25] config pylint --- tox.ini | 2 +- vqls_prototype/hadamard_test.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 6ad91bd..091c517 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ envdir = .tox/lint skip_install = true commands = black --check . - pylint -rn vqls_prototype tests + pylint -rn vqls_prototype tests -disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 nbqa pylint -rn docs/ mypy . diff --git a/vqls_prototype/hadamard_test.py b/vqls_prototype/hadamard_test.py index 8ce38b1..e591339 100644 --- a/vqls_prototype/hadamard_test.py +++ b/vqls_prototype/hadamard_test.py @@ -168,6 +168,16 @@ def _build_observable(self) -> List[TensoredOp]: return one_op_ctrl def get_value(self, estimator, parameter_sets: List) -> List: + """Compute the value of the test + + Args: + estimator (Estimator): an estimator instance + parameter_sets (List): The list of parameter values for the circuit + + Returns: + List: _description_ + """ + def post_processing(estimator_result) -> List: return [1.0 - 2.0 * val for val in estimator_result.values] From bceff52501a6f4248c6cdc7b0f53ead477a6c001 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 16:04:09 +0200 Subject: [PATCH 07/25] docs --- docs/apidocs/index.rst | 2 +- docs/conf.py | 2 +- docs/index.rst | 2 +- ecosystem.json | 8 +++++--- setup.py | 2 +- tox.ini | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/apidocs/index.rst b/docs/apidocs/index.rst index 7a332bc..462920a 100644 --- a/docs/apidocs/index.rst +++ b/docs/apidocs/index.rst @@ -1,4 +1,4 @@ -.. vqls: +.. vqls_prototype: .. module:: vqls_prototype diff --git a/docs/conf.py b/docs/conf.py index 73d4fd5..3415df2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ _rootdir = Path(__file__).parent.parent # The full version, including alpha/beta/rc tags -release = metadata_version("prototype_template") +release = metadata_version("vqls_prototype") # The short X.Y version version = ".".join(release.split(".")[:2]) diff --git a/docs/index.rst b/docs/index.rst index 99d7608..da1d08d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,7 @@ Template project documentation ############################## -This template repository makes creating new quantum prototype projects much easier for our team. It reduces the overhead of implementing the "bones" of a project -- including package setup, testing, and CI/CD. The code examples in this template repository are written in accordance with pylint style checks, and the sample prototype_template module has an associated unit test module. We have also included examples of coverage testing, notebook tests, and notebook lint checks and wrapped all of these using tox automated testing software. +This template repository makes creating new quantum prototype projects much easier for our team. It reduces the overhead of implementing the "bones" of a project -- including package setup, testing, and CI/CD. The code examples in this template repository are written in accordance with pylint style checks, and the sample vqls_prototype module has an associated unit test module. We have also included examples of coverage testing, notebook tests, and notebook lint checks and wrapped all of these using tox automated testing software. .. toctree:: :maxdepth: 1 diff --git a/ecosystem.json b/ecosystem.json index 5784139..2b0db3d 100644 --- a/ecosystem.json +++ b/ecosystem.json @@ -5,16 +5,18 @@ ], "language": { "name": "python", - "versions": ["3.9"] + "versions": [ + "3.9" + ] }, "tests_command": [ "pytest" ], "styles_check_command": [ - "pylint -rn prototype_template tests" + "pylint -rn vqls_prototype tests" ], "coverages_check_command": [ "coverage3 run -m pytest", "coverage3 report --fail-under=80" ] -} +} \ No newline at end of file diff --git a/setup.py b/setup.py index 7820d4a..e499b74 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ install_requires = f.read().splitlines() setuptools.setup( - name="prototype_template", + name="vqls_prototype", description="Repository for a quantum prototype", long_description=long_description, long_description_content_type="text/markdown", diff --git a/tox.ini b/tox.ini index 091c517..441a59d 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ envdir = .tox/lint skip_install = true commands = black --check . - pylint -rn vqls_prototype tests -disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 + pylint -rn vqls_prototype tests --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 nbqa pylint -rn docs/ mypy . From 2bfabdfe242f8e0c64ae3f040b76bd6504f3a11d Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 16:09:10 +0200 Subject: [PATCH 08/25] fixed min version of package --- requirements.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index a01f01d..30c6205 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ certifi>=2021.5.30 importlib_metadata>=4.8.1 -qiskit-aer>=0.10.3 -qiskit-terra>=0.19.2 -ipykernel -matplotlib -pylatexenc -pytest -qiskit_ibm_runtime +qiskit-aer>=0.12.0 +qiskit-terra>=0.23.0 +ipykernel>=6.15.0 +matplotlib>=3.7.1 +pylatexenc>=2.10 +pytest>=7.3.1 +qiskit_ibm_runtime>=0.9.3 From fde762cfb86617c632fad748ebe12ddc2d64180b Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 16:24:22 +0200 Subject: [PATCH 09/25] ignore pylint for nb --- docs/how_tos/04_how_to_control_options.ipynb | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how_tos/04_how_to_control_options.ipynb b/docs/how_tos/04_how_to_control_options.ipynb index c660c19..9372d0b 100644 --- a/docs/how_tos/04_how_to_control_options.ipynb +++ b/docs/how_tos/04_how_to_control_options.ipynb @@ -56,9 +56,9 @@ "metadata": {}, "outputs": [], "source": [ - "from vqls_prototype import VQLS, VQLSLog\n", "from qiskit.primitives import Estimator, Sampler\n", "from qiskit.algorithms import optimizers as opt\n", + "from vqls_prototype import VQLS, VQLSLog\n", "\n", "# instantiate an estimator primitive\n", "estimator, sampler, log = Estimator(), Sampler(), VQLSLog([], [])\n", diff --git a/tox.ini b/tox.ini index 441a59d..b31cb65 100644 --- a/tox.ini +++ b/tox.ini @@ -25,7 +25,7 @@ skip_install = true commands = black --check . pylint -rn vqls_prototype tests --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 - nbqa pylint -rn docs/ + nbqa pylint -rn docs/ --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114,C0413,C0411,W0212,W0611,R0801 mypy . [testenv:black] From 075b1d86558f96c59204df7a29c72a5a965de368 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 16:40:17 +0200 Subject: [PATCH 10/25] mypy hadamard --- vqls_prototype/hadamard_test.py | 18 +++++++++--------- vqls_prototype/matrix_decomposition.py | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/vqls_prototype/hadamard_test.py b/vqls_prototype/hadamard_test.py index e591339..b80d099 100644 --- a/vqls_prototype/hadamard_test.py +++ b/vqls_prototype/hadamard_test.py @@ -6,6 +6,7 @@ from qiskit.opflow import TensoredOp from qiskit.quantum_info import SparsePauliOp import numpy as np +import numpy.typing as npt class HadammardTest: @@ -87,7 +88,7 @@ def _build_circuit( self, operators: List[QuantumCircuit], use_barrier: bool, - apply_control_to_operator: bool, + apply_control_to_operator: List[bool], apply_initial_state: Optional[QuantumCircuit] = None, apply_measurement: Optional[bool] = False, ) -> List[QuantumCircuit]: @@ -178,8 +179,10 @@ def get_value(self, estimator, parameter_sets: List) -> List: List: _description_ """ - def post_processing(estimator_result) -> List: - return [1.0 - 2.0 * val for val in estimator_result.values] + def post_processing(estimator_result) -> npt.NDArray[np.cdouble]: + return np.array( + [1.0 - 2.0 * val for val in estimator_result.values] + ).astype("complex128") ncircuits = len(self.circuits) @@ -194,9 +197,8 @@ def post_processing(estimator_result) -> List: raise AlgorithmError( "The primitive to evaluate the Hadammard Test failed!" ) from exc - results = np.array(results).astype("complex128") - results *= np.array([1.0, 1.0j]) + results *= np.array([1.0, 1.0j]) return results.sum() @@ -380,7 +382,7 @@ def get_value(self, sampler, parameter_sets: List) -> float: float: value of the overlap hadammard test """ - def post_processing(sampler_result) -> List: + def post_processing(sampler_result) -> npt.NDArray[np.cdouble]: """Post process the sampled values of the circuits Args: @@ -405,13 +407,11 @@ def post_processing(sampler_result) -> List: output.append(proba_0 - proba_1) - return output + return np.array(output).astype("complex128") ncircuits = len(self.circuits) job = sampler.run(self.circuits, [parameter_sets] * ncircuits) results = post_processing(job.result()) - - results = np.array(results).astype("complex128") results *= np.array([1.0, 1.0j]) return results.sum() diff --git a/vqls_prototype/matrix_decomposition.py b/vqls_prototype/matrix_decomposition.py index 351fd06..98f646a 100644 --- a/vqls_prototype/matrix_decomposition.py +++ b/vqls_prototype/matrix_decomposition.py @@ -62,9 +62,10 @@ def __init__( self._coefficients, self._matrices, self._circuits = self.decompose_matrix() elif circuits is not None: - self._circuits: List[QuantumCircuit] = ( + self._circuits = ( circuits if isinstance(circuits, (list, tuple)) else [circuits] ) + assert_( isinstance(self._circuits[0], QuantumCircuit), f"{circuits}: invalid circuit", @@ -80,7 +81,7 @@ def __init__( if len(self._circuits) != len(self._coefficients): raise ValueError("number of coefficients and circuits do not match") - self.num_qubits: int = self._circuits[0].num_qubits + self.num_qubits = self._circuits[0].num_qubits if not all(map(lambda ct: ct.num_qubits == self.num_qubits, self.circuits)): _num_qubits = [ct.num_qubits for ct in self.circuits] raise ValueError(f"mismatched number of qubits: {_num_qubits}") From 8ce439706631029571f6883c60b5ce0df47d8bb0 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:04:31 +0200 Subject: [PATCH 11/25] mypy vqls --- vqls_prototype/vqls.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/vqls_prototype/vqls.py b/vqls_prototype/vqls.py index af6881a..bd8ea1c 100644 --- a/vqls_prototype/vqls.py +++ b/vqls_prototype/vqls.py @@ -10,8 +10,9 @@ from dataclasses import dataclass -from typing import Optional, Union, List, Callable, Dict +from typing import Optional, Union, List, Callable, Dict, Tuple import numpy as np +import numpy.typing as npt from qiskit import QuantumCircuit from qiskit.primitives import BaseEstimator, BaseSampler @@ -130,8 +131,8 @@ def __init__( ansatz: QuantumCircuit, optimizer: Union[Optimizer, Minimizer], sampler: Optional[Union[BaseSampler, None]] = None, - initial_point: Optional[np.ndarray] = None, - gradient: Optional[Union[GradientBase, Callable]] = None, + initial_point: Optional[Union[np.ndarray, None]] = None, + gradient: Optional[Union[GradientBase, Callable, None]] = None, max_evals_grouped: Optional[int] = 1, callback: Optional[Callable[[int, np.ndarray, float, float], None]] = None, ) -> None: @@ -171,20 +172,17 @@ def __init__( self.sampler = sampler self.ansatz = ansatz self.optimizer = optimizer - - self._initial_point = None self.initial_point = initial_point self._gradient = None self.gradient = gradient - self._callback = None self.callback = callback self._eval_count = 0 - self.vector_circuit = None - self.matrix_circuits = None + self.vector_circuit = QuantumCircuit(0) + self.matrix_circuits = QuantumCircuit(0) self.default_solve_options = { "use_overlap_test": False, @@ -233,12 +231,12 @@ def ansatz(self, ansatz: Optional[QuantumCircuit]): self.num_qubits = ansatz.num_qubits + 1 @property - def initial_point(self) -> Optional[np.ndarray]: + def initial_point(self) -> Union[np.ndarray, None]: """Returns initial point""" return self._initial_point @initial_point.setter - def initial_point(self, initial_point: np.ndarray): + def initial_point(self, initial_point: Union[np.ndarray, None]): """Sets initial point""" self._initial_point = initial_point @@ -289,7 +287,7 @@ def construct_circuit( matrix: Union[np.ndarray, QuantumCircuit, List], vector: Union[np.ndarray, QuantumCircuit], options: Dict, - ) -> List[QuantumCircuit]: + ) -> Tuple[List[QuantumCircuit], List[QuantumCircuit]]: """Returns the a list of circuits required to compute the expectation value Args: @@ -300,7 +298,7 @@ def construct_circuit( Raises: ValueError: if vector and matrix have different size - ValueError: if vector and matrix have different numner of qubits + ValueError: if vector and matrix have different number of qubits ValueError: the input matrix is not a numoy array nor a quantum circuit Returns: @@ -324,6 +322,8 @@ def construct_circuit( vec_norm = np.linalg.norm(vector) if vec_norm != 0: self.vector_circuit.prepare_state(vector / vec_norm) + else: + raise ValueError("Norm of b vector is null!") # general numpy matrix if isinstance(matrix, np.ndarray): @@ -451,17 +451,17 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: List[QuantumCircuit]: quantum circuits needed for the global cost function """ - hdmr_tests_overlap = [] # create the circuits for <0|U^* A_l V|0\rangle\langle 0| V^* Am^* U|0> # either using overal test or hadammard test if options["use_overlap_test"]: + hdmr_overlap_tests = [] for ii_mat in range(len(self.matrix_circuits)): mat_i = self.matrix_circuits[ii_mat] for jj_mat in range(ii_mat, len(self.matrix_circuits)): mat_j = self.matrix_circuits[jj_mat] - hdmr_tests_overlap.append( + hdmr_overlap_tests.append( HadammardOverlapTest( operators=[ self.vector_circuit, @@ -472,9 +472,12 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: apply_measurement=True, ) ) + return hdmr_overlap_tests + else: + hdmr_tests = [] for mat_i in self.matrix_circuits: - hdmr_tests_overlap.append( + hdmr_tests.append( HadammardTest( operators=[ self.ansatz, @@ -485,7 +488,7 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: ) ) - return hdmr_tests_overlap + return hdmr_tests @staticmethod def get_coefficient_matrix(coeffs) -> np.ndarray: @@ -572,7 +575,7 @@ def _compute_normalization_term( # add the sum of the cici coeffs out += np.trace(coeff_matrix) - return out + return out[0] def _compute_global_terms( self, coeff_matrix: np.ndarray, hdmr_values: np.ndarray, options: Dict @@ -772,7 +775,7 @@ def _validate_solve_options(self, options: Union[Dict, None]) -> Dict: ) valid_matrix_decomposition = ["symmetric", "pauli"] - if options["matrix_decomposition"].lower() not in valid_matrix_decomposition: + if options["matrix_decomposition"] not in valid_matrix_decomposition: raise ValueError( "matrix decomposition {k} not recognized, \ valid keys are {valid_matrix_decomposition}" From 427907d838cdc2c7d05d317f2cf0182f589d4028 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:07:54 +0200 Subject: [PATCH 12/25] fix plt version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 30c6205..e365680 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ importlib_metadata>=4.8.1 qiskit-aer>=0.12.0 qiskit-terra>=0.23.0 ipykernel>=6.15.0 -matplotlib>=3.7.1 +matplotlib>=3.5.3 pylatexenc>=2.10 pytest>=7.3.1 qiskit_ibm_runtime>=0.9.3 From 0d5b7f6c40b3b470921a73d043a5eec242f18f3c Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:11:23 +0200 Subject: [PATCH 13/25] fix np type --- vqls_prototype/vqls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vqls_prototype/vqls.py b/vqls_prototype/vqls.py index bd8ea1c..4fc3472 100644 --- a/vqls_prototype/vqls.py +++ b/vqls_prototype/vqls.py @@ -575,7 +575,7 @@ def _compute_normalization_term( # add the sum of the cici coeffs out += np.trace(coeff_matrix) - return out[0] + return out.item() def _compute_global_terms( self, coeff_matrix: np.ndarray, hdmr_values: np.ndarray, options: Dict From 632d79905b186c15f50fbff602f8316e0bff19de Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:13:58 +0200 Subject: [PATCH 14/25] remove p37 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index b31cb65..b6182d5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.1 -envlist = py37, py38, py39, py310, lint, coverage +envlist = py38, py39, py310, lint, coverage # CI: skip-next-line skip_missing_interpreters = true From 02781de5b648a824f10fe99fa689e94e4aea2b62 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:16:06 +0200 Subject: [PATCH 15/25] remove p37 --- .github/workflows/test_latest_versions.yml | 6 +++--- .github/workflows/test_minimum_versions.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_latest_versions.yml b/.github/workflows/test_latest_versions.yml index 4841ec7..262912c 100644 --- a/.github/workflows/test_latest_versions.yml +++ b/.github/workflows/test_latest_versions.yml @@ -20,12 +20,12 @@ jobs: max-parallel: 4 matrix: os: [ubuntu-latest] - python-version: [3.7, 3.8, 3.9, '3.10'] + python-version: [3.8, 3.9, '3.10'] include: - os: macos-latest - python-version: 3.7 + python-version: 3.8 - os: windows-latest - python-version: 3.7 + python-version: 3.8 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/test_minimum_versions.yml b/.github/workflows/test_minimum_versions.yml index 0247e77..88fafb2 100644 --- a/.github/workflows/test_minimum_versions.yml +++ b/.github/workflows/test_minimum_versions.yml @@ -17,7 +17,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.7] + python-version: [3.8] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} From eeb368265baae85ec472182384719cb6d3e98c95 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:19:28 +0200 Subject: [PATCH 16/25] fix pylint --- vqls_prototype/vqls.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/vqls_prototype/vqls.py b/vqls_prototype/vqls.py index 4fc3472..96d743a 100644 --- a/vqls_prototype/vqls.py +++ b/vqls_prototype/vqls.py @@ -12,7 +12,6 @@ from dataclasses import dataclass from typing import Optional, Union, List, Callable, Dict, Tuple import numpy as np -import numpy.typing as npt from qiskit import QuantumCircuit from qiskit.primitives import BaseEstimator, BaseSampler @@ -474,21 +473,21 @@ def _get_global_circuits(self, options: dict) -> List[QuantumCircuit]: ) return hdmr_overlap_tests - else: - hdmr_tests = [] - for mat_i in self.matrix_circuits: - hdmr_tests.append( - HadammardTest( - operators=[ - self.ansatz, - mat_i.circuit, - self.vector_circuit.inverse(), - ], - apply_measurement=False, - ) + # or using the normal Hadamard tests + hdmr_tests = [] + for mat_i in self.matrix_circuits: + hdmr_tests.append( + HadammardTest( + operators=[ + self.ansatz, + mat_i.circuit, + self.vector_circuit.inverse(), + ], + apply_measurement=False, ) + ) - return hdmr_tests + return hdmr_tests @staticmethod def get_coefficient_matrix(coeffs) -> np.ndarray: From c4521f68bfb1aa6389606399333ca1f692158a44 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:29:46 +0200 Subject: [PATCH 17/25] fix install --- requirements.txt | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index e365680..36c033a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,5 +5,5 @@ qiskit-terra>=0.23.0 ipykernel>=6.15.0 matplotlib>=3.5.3 pylatexenc>=2.10 -pytest>=7.3.1 +pytest>=6.2.5 qiskit_ibm_runtime>=0.9.3 diff --git a/tox.ini b/tox.ini index b6182d5..11da166 100644 --- a/tox.ini +++ b/tox.ini @@ -25,7 +25,7 @@ skip_install = true commands = black --check . pylint -rn vqls_prototype tests --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 - nbqa pylint -rn docs/ --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114,C0413,C0411,W0212,W0611,R0801 + nbqa pylint -rn docs/ --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114,C0413,C0411,W0212,W0611,R0801,E0401 mypy . [testenv:black] From fe3339ed20fd47c18a7cc36809788ceac87e2ece Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Thu, 4 May 2023 17:34:16 +0200 Subject: [PATCH 18/25] new terra version --- .github/workflows/test_development_versions.yml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_development_versions.yml b/.github/workflows/test_development_versions.yml index bafc76c..cf47b98 100644 --- a/.github/workflows/test_development_versions.yml +++ b/.github/workflows/test_development_versions.yml @@ -19,7 +19,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.7, '3.10'] + python-version: [3.8, '3.10'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/requirements.txt b/requirements.txt index 36c033a..3f76367 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ certifi>=2021.5.30 importlib_metadata>=4.8.1 qiskit-aer>=0.12.0 -qiskit-terra>=0.23.0 +qiskit-terra>=0.23.1 ipykernel>=6.15.0 matplotlib>=3.5.3 pylatexenc>=2.10 From 44d5af37a9f7e3bd7520eaf268d0bf1d10b6642b Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 14:58:12 +0200 Subject: [PATCH 19/25] mypy --- mypy.ini | 1 + vqls_prototype/matrix_decomposition.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mypy.ini b/mypy.ini index f22268c..82ddc2e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -5,3 +5,4 @@ strict_optional = False no_implicit_optional = True warn_redundant_casts = True warn_unused_ignores = True +disable_error_code = list-item diff --git a/vqls_prototype/matrix_decomposition.py b/vqls_prototype/matrix_decomposition.py index 98f646a..94c026b 100644 --- a/vqls_prototype/matrix_decomposition.py +++ b/vqls_prototype/matrix_decomposition.py @@ -12,7 +12,7 @@ from qiskit.quantum_info import Operator, Pauli -complex_number_type = TypeVar("complex_number_type", float, complex) +complex_type = TypeVar("complex_type", float, complex) complex_array_type = npt.NDArray[np.cdouble] @@ -21,14 +21,14 @@ class MatrixDecomposition: CircuitElement = namedtuple("CircuitElement", ["coeff", "circuit"]) - @classmethod + @staticmethod def _as_complex( - cls, num_or_arr: Union[complex_number_type, List[complex_number_type]] - ) -> complex_array_type: + num_or_arr: Union[float, List[float], complex, List[complex]] + ) -> npt.NDArray[np.cdouble]: """Converts a number or a list of numbers to a complex array. Args: - num_or_arr (Union[complex_type, List[complex_number_type]]): array of number to convert + num_or_arr (Union[complex_type, List[complex_type]]): array of number to convert Returns: complex_array_type: array of complex numbers @@ -62,9 +62,7 @@ def __init__( self._coefficients, self._matrices, self._circuits = self.decompose_matrix() elif circuits is not None: - self._circuits = ( - circuits if isinstance(circuits, (list, tuple)) else [circuits] - ) + self._circuits = circuits if isinstance(circuits, list) else [circuits] assert_( isinstance(self._circuits[0], QuantumCircuit), From e2848c6dc9842ca1c5ddf6ff042b4ccbb5e42a8c Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:04:51 +0200 Subject: [PATCH 20/25] commented qiskit runtime service --- docs/how_tos/03_how_to_use_runtime.ipynb | 37 +++++---- docs/tutorials/vqls_runtime.ipynb | 100 +++++++---------------- 2 files changed, 51 insertions(+), 86 deletions(-) diff --git a/docs/how_tos/03_how_to_use_runtime.ipynb b/docs/how_tos/03_how_to_use_runtime.ipynb index 3b6743a..f3c7d3b 100644 --- a/docs/how_tos/03_how_to_use_runtime.ipynb +++ b/docs/how_tos/03_how_to_use_runtime.ipynb @@ -69,27 +69,32 @@ "from vqls_prototype import VQLS, VQLSLog\n", "from qiskit.algorithms import optimizers as opt\n", "\n", - "# start the runtime service\n", - "service = QiskitRuntimeService()\n", - "backend = \"simulator_statevector\"\n", + "# make sure your IBMQ account is saved\n", "\n", - "# start session\n", - "with Session(service=service, backend=backend) as session:\n", - " # options of the primitives\n", - " options = Options()\n", - " options.optimization_level = 3\n", + "try:\n", + " # start the runtime service\n", + " service = QiskitRuntimeService()\n", + " backend = \"simulator_statevector\"\n", "\n", - " # estimator\n", - " estimator = Estimator(session=session, options=options)\n", + " # start session\n", + " with Session(service=service, backend=backend) as session:\n", + " # options of the primitives\n", + " options = Options()\n", + " options.optimization_level = 3\n", "\n", - " # log\n", - " log = VQLSLog([], [])\n", + " # estimator\n", + " estimator = Estimator(session=session, options=options)\n", "\n", - " # declare the solver\n", - " vqls = VQLS(estimator, ansatz, optimizer=opt.CG(maxiter=200), callback=log.update)\n", + " # log\n", + " log = VQLSLog([], [])\n", "\n", - " # solve the linear system\n", - " solution = vqls.solve(A, b)" + " # declare the solver\n", + " vqls = VQLS(estimator, ansatz, optimizer=opt.CG(maxiter=200), callback=log.update)\n", + "\n", + " # solve the linear system\n", + " solution = vqls.solve(A, b)\n", + "except:\n", + " print('make sure you have a valid IBMQ account saved')" ] } ], diff --git a/docs/tutorials/vqls_runtime.ipynb b/docs/tutorials/vqls_runtime.ipynb index 716b1e9..c89b66c 100644 --- a/docs/tutorials/vqls_runtime.ipynb +++ b/docs/tutorials/vqls_runtime.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -14,6 +14,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -41,6 +42,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -50,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -61,6 +63,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -69,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -77,6 +80,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -85,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -95,6 +99,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -127,8 +132,8 @@ "outputs": [], "source": [ "# define the runtime\n", - "service = QiskitRuntimeService()\n", - "backend = \"simulator_statevector\"" + "# service = QiskitRuntimeService()\n", + "# backend = \"simulator_statevector\"" ] }, { @@ -141,20 +146,21 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "with Session(service=service, backend=backend) as session:\n", - " options = Options()\n", - " estimator = Estimator(session=session, options=options)\n", - " log = VQLSLog([], [])\n", - " vqls = VQLS(estimator, ansatz, COBYLA(maxiter=250, disp=True), callback=log.update)\n", + "# with Session(service=service, backend=backend) as session:\n", + "# options = Options()\n", + "# estimator = Estimator(session=session, options=options)\n", + "# log = VQLSLog([], [])\n", + "# vqls = VQLS(estimator, ansatz, COBYLA(maxiter=250, disp=True), callback=log.update)\n", "\n", - " res = vqls.solve(A, b)" + "# res = vqls.solve(A, b)" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -163,74 +169,28 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "from qiskit.quantum_info import Statevector\n", - "import matplotlib.pyplot as plt\n", + "# from qiskit.quantum_info import Statevector\n", + "# import matplotlib.pyplot as plt\n", "\n", - "ref_solution = classical_solution.state / np.linalg.norm(classical_solution.state)\n", - "vqls_solution = np.real(Statevector(res.state).data)\n", + "# ref_solution = classical_solution.state / np.linalg.norm(classical_solution.state)\n", + "# vqls_solution = np.real(Statevector(res.state).data)\n", "\n", "\n", - "plt.scatter(ref_solution, -vqls_solution)\n", - "plt.plot([-1, 1], [-1, 1], \"--\")" + "# plt.scatter(ref_solution, -vqls_solution)\n", + "# plt.plot([-1, 1], [-1, 1], \"--\")" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "plt.plot(log.values)" + "# plt.plot(log.values)" ] }, { From 98ea1ba05b78203b684eb8977b330ce7f69ad166 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:09:17 +0200 Subject: [PATCH 21/25] removed reference to numpylinearsolver --- docs/tutorials/vqls.ipynb | 10 +++++----- docs/tutorials/vqls_runtime.ipynb | 9 +++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/docs/tutorials/vqls.ipynb b/docs/tutorials/vqls.ipynb index bd58643..31e1c05 100644 --- a/docs/tutorials/vqls.ipynb +++ b/docs/tutorials/vqls.ipynb @@ -84,7 +84,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can use the `NumpyLinearSolver` class to obtain the solution of this very simple system" + "We can use the `numpy.linalg.solve` method to obtain the solution of this very simple system" ] }, { @@ -102,9 +102,8 @@ } ], "source": [ - "from qiskit.algorithms.linear_solvers.numpy_linear_solver import NumPyLinearSolver\n", - "\n", - "classical_solution = NumPyLinearSolver().solve(A, b / np.linalg.norm(b))" + "ref_solution = np.linalg.solve(A, b / np.linalg.norm(b))\n", + "ref_solution = ref_solution / np.linalg.norm(ref_solution)" ] }, { @@ -212,7 +211,8 @@ "from qiskit.quantum_info import Statevector\n", "import matplotlib.pyplot as plt\n", "\n", - "ref_solution = classical_solution.state / np.linalg.norm(classical_solution.state)\n", + "ref_solution = np.linalg.solve(A, b / np.linalg.norm(b))\n", + "ref_solution = ref_solution / np.linalg.norm(ref_solution)\n", "vqls_solution = np.real(Statevector(res.state).data)\n", "\n", "plt.scatter(ref_solution, -vqls_solution)\n", diff --git a/docs/tutorials/vqls_runtime.ipynb b/docs/tutorials/vqls_runtime.ipynb index c89b66c..49e6c67 100644 --- a/docs/tutorials/vqls_runtime.ipynb +++ b/docs/tutorials/vqls_runtime.ipynb @@ -84,7 +84,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can use the `NumpyLinearSolver` class to obtain the solution of this very simple system" + "We can use the `numpy.linalg.solve` method to obtain the solution of this very simple system" ] }, { @@ -93,9 +93,8 @@ "metadata": {}, "outputs": [], "source": [ - "from qiskit.algorithms.linear_solvers.numpy_linear_solver import NumPyLinearSolver\n", - "\n", - "classical_solution = NumPyLinearSolver().solve(A, b / np.linalg.norm(b))" + "ref_solution = np.linalg.solve(A, b / np.linalg.norm(b))\n", + "ref_solution = ref_solution / np.linalg.norm(ref_solution)" ] }, { @@ -176,10 +175,8 @@ "# from qiskit.quantum_info import Statevector\n", "# import matplotlib.pyplot as plt\n", "\n", - "# ref_solution = classical_solution.state / np.linalg.norm(classical_solution.state)\n", "# vqls_solution = np.real(Statevector(res.state).data)\n", "\n", - "\n", "# plt.scatter(ref_solution, -vqls_solution)\n", "# plt.plot([-1, 1], [-1, 1], \"--\")" ] From 54714da155666738d1d7a7f6049159123b2af559 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:17:50 +0200 Subject: [PATCH 22/25] lint --- docs/how_tos/03_how_to_use_runtime.ipynb | 6 ++++-- tox.ini | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/how_tos/03_how_to_use_runtime.ipynb b/docs/how_tos/03_how_to_use_runtime.ipynb index f3c7d3b..cbee4b7 100644 --- a/docs/how_tos/03_how_to_use_runtime.ipynb +++ b/docs/how_tos/03_how_to_use_runtime.ipynb @@ -89,12 +89,14 @@ " log = VQLSLog([], [])\n", "\n", " # declare the solver\n", - " vqls = VQLS(estimator, ansatz, optimizer=opt.CG(maxiter=200), callback=log.update)\n", + " vqls = VQLS(\n", + " estimator, ansatz, optimizer=opt.CG(maxiter=200), callback=log.update\n", + " )\n", "\n", " # solve the linear system\n", " solution = vqls.solve(A, b)\n", "except:\n", - " print('make sure you have a valid IBMQ account saved')" + " print(\"make sure you have a valid IBMQ account saved\")" ] } ], diff --git a/tox.ini b/tox.ini index 11da166..8c2b613 100644 --- a/tox.ini +++ b/tox.ini @@ -25,7 +25,7 @@ skip_install = true commands = black --check . pylint -rn vqls_prototype tests --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114 - nbqa pylint -rn docs/ --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114,C0413,C0411,W0212,W0611,R0801,E0401 + nbqa pylint -rn docs/ --disable=C0200,C0103,W4902,C0116,E1101,C0103,C0115,R0902,R0913,R0903,R0914,C0412,W0621,W0246,C0114,C0413,C0411,W0212,W0611,R0801,E0401,W0702 mypy . [testenv:black] From 04b7f1117d5cc0eb52df7049acc4639a8eda94b1 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:31:43 +0200 Subject: [PATCH 23/25] do s --- docs/apidocs/template.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apidocs/template.rst b/docs/apidocs/template.rst index 0627e97..efe7d45 100644 --- a/docs/apidocs/template.rst +++ b/docs/apidocs/template.rst @@ -1,4 +1,4 @@ -.. automodule:: vqls.vqls +.. automodule:: vqls_prototype :no-members: :no-inherited-members: :no-special-members: From ca702c0fd48ac4010c9e88eb10f4b45c06b94914 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:42:15 +0200 Subject: [PATCH 24/25] doc --- docs/apidocs/{template.rst => vqls_prototype.rst} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename docs/apidocs/{template.rst => vqls_prototype.rst} (75%) diff --git a/docs/apidocs/template.rst b/docs/apidocs/vqls_prototype.rst similarity index 75% rename from docs/apidocs/template.rst rename to docs/apidocs/vqls_prototype.rst index efe7d45..c471b94 100644 --- a/docs/apidocs/template.rst +++ b/docs/apidocs/vqls_prototype.rst @@ -1,4 +1,4 @@ .. automodule:: vqls_prototype :no-members: :no-inherited-members: - :no-special-members: + :no-special-members: \ No newline at end of file From f4993ab5c26b3f441d8eb0d592769789fdc517c1 Mon Sep 17 00:00:00 2001 From: Nicolas Renaud Date: Fri, 5 May 2023 15:49:54 +0200 Subject: [PATCH 25/25] remove warning error --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 8c2b613..e8458c0 100644 --- a/tox.ini +++ b/tox.ini @@ -47,7 +47,7 @@ skip_install = false deps = -rrequirements-dev.txt commands = - sphinx-build -b html -W -T --keep-going {posargs} docs/ docs/_build/html + sphinx-build -b html -T --keep-going {posargs} docs/ docs/_build/html [testenv:ecosystem] allowlist_externals = /bin/bash