From 7665cc0c167c24c1992be1f799a64e1732cbbb0e Mon Sep 17 00:00:00 2001 From: Melvin Strobl Date: Thu, 14 Nov 2024 07:50:59 +0100 Subject: [PATCH 1/5] optional none input Signed-off-by: Melvin Strobl --- qml_essentials/expressibility.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/qml_essentials/expressibility.py b/qml_essentials/expressibility.py index 924ef67..9f26d95 100644 --- a/qml_essentials/expressibility.py +++ b/qml_essentials/expressibility.py @@ -33,16 +33,16 @@ def _sample_state_fidelities( """ rng = np.random.default_rng(seed) - # Number of input samples + # Generate random parameter sets + # We need two sets of parameters, as we are computing fidelities for a + # pair of random state vectors + model.initialize_params(rng=rng, repeat=n_samples * 2) + n_x_samples = len(x_samples) # Initialize array to store fidelities fidelities: np.ndarray = np.zeros((n_x_samples, n_samples)) - # Generate random parameter sets - # We need two sets of parameters, as we are computing fidelities for a - # pair of random state vectors - model.initialize_params(rng=rng, repeat=n_samples * 2) # Batch input samples and parameter sets for efficient computation x_samples_batched: np.ndarray = x_samples.reshape(1, -1).repeat( n_samples * 2, axis=0 @@ -70,6 +70,7 @@ def _sample_state_fidelities( ) ** 2 ) + # TODO: abs instead? fidelities[idx] = np.real(fidelity) return fidelities @@ -101,7 +102,11 @@ def state_fidelities( input samples, bin edges, and histogram values. """ - x = np.linspace(*input_domain, n_input_samples, requires_grad=False) + if input_domain is None or n_input_samples is None or n_input_samples == 0: + x = np.zeros((1)) + n_input_samples = 1 + else: + x = np.linspace(*input_domain, n_input_samples, requires_grad=False) fidelities = Expressibility._sample_state_fidelities( x_samples=x, From d9413a8cabe58c58602423db997c72dbe9e5144b Mon Sep 17 00:00:00 2001 From: Melvin Strobl Date: Thu, 14 Nov 2024 11:14:17 +0100 Subject: [PATCH 2/5] added n input nonable and test Signed-off-by: Melvin Strobl --- qml_essentials/expressibility.py | 15 ++++++++++++++- tests/test_expressiblity.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/qml_essentials/expressibility.py b/qml_essentials/expressibility.py index 9f26d95..65075c4 100644 --- a/qml_essentials/expressibility.py +++ b/qml_essentials/expressibility.py @@ -83,6 +83,7 @@ def state_fidelities( n_input_samples: int, input_domain: List[float], model: Model, + scale: bool = False, **kwargs: Any, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """ @@ -95,12 +96,16 @@ def state_fidelities( n_input_samples (int): Number of input samples. input_domain (List[float]): Input domain. model (Callable): Function that models the quantum circuit. + scale (bool): Whether to scale the number of samples and bins. kwargs (Any): Additional keyword arguments for the model function. Returns: Tuple[np.ndarray, np.ndarray, np.ndarray]: Tuple containing the input samples, bin edges, and histogram values. """ + if scale: + n_samples = np.power(2, model.n_qubits) * n_samples + n_bins = model.n_qubits * n_bins if input_domain is None or n_input_samples is None or n_input_samples == 0: x = np.zeros((1)) @@ -124,6 +129,9 @@ def state_fidelities( z = z / n_samples + if z.shape[0] == 1: + z = z.flatten() + return x, y, z @staticmethod @@ -173,6 +181,7 @@ def haar_integral( n_qubits: int, n_bins: int, cache: bool = True, + scale: bool = False, ) -> Tuple[np.ndarray, np.ndarray]: """ Calculates theoretical probability density function for random Haar states @@ -183,6 +192,7 @@ def haar_integral( n_qubits (int): number of qubits in the quantum system n_bins (int): number of histogram bins cache (bool): whether to cache the haar integral + scale (bool): whether to scale the number of bins Returns: Tuple[np.ndarray, np.ndarray]: @@ -190,10 +200,13 @@ def haar_integral( - y component (probabilities): the haar probability density funtion for random Haar states """ + if scale: + n_bins = n_qubits * n_bins + x = np.linspace(0, 1, n_bins) if cache: - name = f"haar_{n_qubits}q_{n_bins}s.npy" + name = f"haar_{n_qubits}q_{n_bins}s_{'scaled' if scale else ''}.npy" cache_folder = ".cache" if not os.path.exists(cache_folder): diff --git a/tests/test_expressiblity.py b/tests/test_expressiblity.py index d7b8671..4983d85 100644 --- a/tests/test_expressiblity.py +++ b/tests/test_expressiblity.py @@ -94,3 +94,34 @@ def test_expressibility() -> None: ), f"Expressibility is not {test_case['result']}\ for circuit ansatz {test_case['circuit_type']}.\ Was {kl_dist} instead" + + +@pytest.mark.unittest +@pytest.mark.expensive +def test_scaling() -> None: + model = Model( + n_qubits=2, + n_layers=1, + circuit_type="Circuit_1", + ) + + _, _, z = Expressibility.state_fidelities( + seed=1000, + n_bins=4, + n_samples=10, + n_input_samples=0, + input_domain=[0, 2 * np.pi], + model=model, + scale=True, + ) + + assert z.shape == (8,) + + _, y = Expressibility.haar_integral( + n_qubits=model.n_qubits, + n_bins=4, + cache=True, + scale=True, + ) + + assert y.shape == (8,) From e8aa652c605395a1db31a84f0ba00308fa5b2c0d Mon Sep 17 00:00:00 2001 From: Melvin Strobl Date: Thu, 14 Nov 2024 11:19:51 +0100 Subject: [PATCH 3/5] added kl div check Signed-off-by: Melvin Strobl --- tests/test_expressiblity.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_expressiblity.py b/tests/test_expressiblity.py index 4983d85..cb28214 100644 --- a/tests/test_expressiblity.py +++ b/tests/test_expressiblity.py @@ -120,8 +120,10 @@ def test_scaling() -> None: _, y = Expressibility.haar_integral( n_qubits=model.n_qubits, n_bins=4, - cache=True, + cache=False, scale=True, ) assert y.shape == (8,) + + _ = Expressibility.kullback_leibler_divergence(z, y) From 8bad289e841c08f94ee3a495bed5136b4eb68d72 Mon Sep 17 00:00:00 2001 From: Melvin Strobl Date: Fri, 15 Nov 2024 09:53:34 +0100 Subject: [PATCH 4/5] moved list Signed-off-by: Melvin Strobl --- qml_essentials/model.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qml_essentials/model.py b/qml_essentials/model.py index e935868..9b26b1c 100644 --- a/qml_essentials/model.py +++ b/qml_essentials/model.py @@ -595,9 +595,10 @@ def _forward( inputs=inputs, ) + if isinstance(result, list): + result = np.stack(result) + if self.execution_type == "expval" and self.output_qubit == -1: - if isinstance(result, list): - result = np.stack(result) # Calculating mean value after stacking, to not # discard gradient information From 9bbe5fff68dec89cdaff955f6bdee41d5570d4d4 Mon Sep 17 00:00:00 2001 From: Melvin Strobl Date: Fri, 15 Nov 2024 10:58:52 +0100 Subject: [PATCH 5/5] bumped version Signed-off-by: Melvin Strobl --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e823371..0771593 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "qml-essentials" -version = "0.1.16" +version = "0.1.17" description = "" authors = ["Melvin Strobl ", "Maja Franz "] readme = "README.md"