-
-
Notifications
You must be signed in to change notification settings - Fork 13
Gradient-Free Noise Characterization #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a9b2115
e4c5def
9698629
15b5530
329841c
2a41de5
96896fd
6e71232
f994a10
c34513d
0790872
0245b7b
9096728
6e2b98d
fc24da1
8fe948e
cf66d5a
d800d2e
b162230
5ca20d6
e29a9e4
44b710b
e9a66de
ac5974f
3f0ebb1
cfc6fe0
fa9b3e9
6a44563
d7001d3
4988b4b
9da7af2
c985972
f5a63fe
1742789
dae45a1
261577f
6556952
7cb8f2f
5039960
94e02f4
280b831
da10f8b
c346c09
0e18091
4be9d95
ff92071
10882e2
e5ab9c6
44e398a
543633f
9b0dcde
a91a975
aee5c8c
788c57b
2880a68
b9f9976
3b71ce4
6f145e4
fd20718
fa09731
06e990c
f0d0c2d
f932a7c
2ee280b
17a85aa
bab111c
6d6e935
88dc32b
7200dc5
97c7965
825a68a
9d2dcf4
72a1dca
abb88be
54450c2
af580ac
986a9c3
ec99a58
3cf23af
6c8dae5
1e15a0c
bf5f2a3
3b45437
0d4dacd
e9e5bd6
4760b92
0836500
d3d991b
6d741d7
57edcd2
731378e
f1ef614
3303f86
506db16
2363bc8
5f31d8e
3a711cf
9d48e32
1454c99
fe1710f
afe72bb
d30eeae
75cea9f
f5322f8
ea8db23
2e455de
40f9396
79185f6
6d023a9
6729ec2
02c6784
6b2bdf5
05c5ee8
c0a9482
6ebbc1c
cf51699
9650d6f
3de65ac
d8a2748
cd8b734
6c00925
9286360
b5de1de
29ff6de
bc6197c
56e9f52
1cfbc2d
7026649
cbd6a0b
f29740a
f3d8a4f
5b723c4
f8cdd8a
e68aa1a
44085d5
14f6c85
974935b
778d422
ab9e7e9
9abeebf
7c0b389
6a19e00
fc81ff7
6d68fa0
9bc909f
1a931e1
cdcdd12
9107502
3a9cf06
8f152e3
daded0d
e8395fe
8269ebf
edba728
176fa53
cdffa1a
8bc7f38
d7b5761
6550add
57a155c
7c5c595
dac5ebf
8139a43
bb69f33
fa91a51
ec87774
5487153
58a6bae
03bda97
b474930
01ac5ed
b7cd691
0278785
ce737ed
7bd6e01
9a1d51f
6031fcb
6d10d3e
e681578
53d07e7
c890080
0592466
c97c9e7
770be2f
1d24a8a
e063941
c9c8ce6
900dd19
b66ad6f
e58c188
3de2c7d
94c1b87
c0893fc
f17f2a5
d1f6f87
e4e2a62
b7ef2c0
5f6069c
2e02f13
59eb2d6
c4be271
f3094c6
8adc2a7
02584a8
90b2001
a8bcd3a
6c3f99b
65e9450
6bc08e8
5b17a9f
a2a92b6
3006230
c068cb1
6aec7c5
db24aa1
3cb9909
5744862
e7fb6db
0d6e745
401d8a1
3a86741
9ca87ec
1a71fd8
4287ec0
c7bc658
e59959c
eb16af4
ae5c659
2f4ae57
37e6254
95ab06c
7b4929d
dbaa882
7e0814a
8005500
7235340
85dfa6e
f1e7769
07fbb61
250c142
73a8951
b3fb82a
ecc4b16
c3d7dc8
5ae8e1d
e2c02a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,140 @@ | ||||||||||
| # Characterizer example | ||||||||||
|
|
||||||||||
| This document contains the example script `characterizer_example.py` converted to Markdown. It shows how to set up a simple Ising Hamiltonian, generate a reference trajectory with a given noise model, build a LossClass and Characterizer, and run the optimizer. | ||||||||||
|
|
||||||||||
| ## Requirements | ||||||||||
|
|
||||||||||
| - numpy | ||||||||||
| - mqt.yaqs package (propagation, optimization, characterizer, core.data_structures) | ||||||||||
| - A working environment where PropagatorWithGradients can run (the example uses the package's propagator) | ||||||||||
|
|
||||||||||
| ## Usage | ||||||||||
|
|
||||||||||
| Copy the Python code block below into a `.py` file and run it, or execute the cells if using a notebook. | ||||||||||
|
|
||||||||||
| ```python | ||||||||||
| import numpy as np | ||||||||||
| from pathlib import Path | ||||||||||
|
|
||||||||||
| from mqt.yaqs.noise_char.propagation import PropagatorWithGradients | ||||||||||
| from mqt.yaqs.noise_char.optimization import LossClass | ||||||||||
| from mqt.yaqs.noise_char.characterizer import Characterizer | ||||||||||
|
|
||||||||||
| from mqt.yaqs.core.data_structures.networks import MPO, MPS | ||||||||||
| from mqt.yaqs.core.data_structures.noise_model import CompactNoiseModel | ||||||||||
| from mqt.yaqs.core.data_structures.simulation_parameters import ( | ||||||||||
| AnalogSimParams, | ||||||||||
| Observable, | ||||||||||
| ) | ||||||||||
| from mqt.yaqs.core.libraries.gate_library import X, Y, Z, Create, Destroy | ||||||||||
|
|
||||||||||
| if __name__ == "__main__": | ||||||||||
| work_dir = "test/scikit_characterizer/" | ||||||||||
| work_dir_path = Path(work_dir) | ||||||||||
| work_dir_path.mkdir(parents=True, exist_ok=True) | ||||||||||
|
|
||||||||||
|
Comment on lines
+32
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Prefer consistent use of Path objects. Line 33 creates a string path, Line 34 converts it to a Path object, but Line 86 continues to use the string version. For consistency and cross-platform compatibility, prefer using ♻️ Suggested refactor for consistent Path usage- work_dir = "test/scikit_characterizer/"
- work_dir_path = Path(work_dir)
+ work_dir_path = Path("test/scikit_characterizer/")
work_dir_path.mkdir(parents=True, exist_ok=True)And update Line 86: - work_dir + "gammas.txt", ref_noise_model.strength_list, header="##", fmt="%.6f"
+ work_dir_path / "gammas.txt", ref_noise_model.strength_list, header="##", fmt="%.6f"
🤖 Prompt for AI Agents |
||||||||||
| # Defining Hamiltonian and observable list | ||||||||||
| L = 2 | ||||||||||
| J = 1 | ||||||||||
| g = 0.5 | ||||||||||
|
|
||||||||||
| H_0 = MPO() | ||||||||||
| H_0.init_ising(L, J, g) | ||||||||||
|
|
||||||||||
| # Define the initial state | ||||||||||
| init_state = MPS(L, state="zeros") | ||||||||||
|
|
||||||||||
| obs_list = [Observable(X(), site) for site in range(L)] | ||||||||||
|
|
||||||||||
| noise_operator = "pauli_y" | ||||||||||
|
|
||||||||||
| # Defining simulation parameters | ||||||||||
| T = 3 | ||||||||||
| dt = 0.1 | ||||||||||
| N = 1000 | ||||||||||
| max_bond_dim = 8 | ||||||||||
| threshold = 1e-6 | ||||||||||
| order = 1 | ||||||||||
|
|
||||||||||
| sim_params = AnalogSimParams( | ||||||||||
| observables=obs_list, | ||||||||||
| elapsed_time=T, | ||||||||||
| dt=dt, | ||||||||||
| num_traj=N, | ||||||||||
| max_bond_dim=max_bond_dim, | ||||||||||
| threshold=threshold, | ||||||||||
| order=order, | ||||||||||
| sample_timesteps=True, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| # Defining reference noise model and reference trajectory | ||||||||||
| gamma_reference = 0.1 | ||||||||||
|
|
||||||||||
| ref_noise_model = CompactNoiseModel( | ||||||||||
| [ | ||||||||||
| { | ||||||||||
| "name": noise_operator, | ||||||||||
| "sites": [i for i in range(L)], | ||||||||||
| "strength": gamma_reference, | ||||||||||
|
Comment on lines
+77
to
+78
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Simplify list comprehension. The pattern ♻️ Suggested simplification- "sites": [i for i in range(L)],
+ "sites": list(range(L)),Similarly for line 113: - "sites": [i for i in range(L)],
+ "sites": list(range(L)),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| } | ||||||||||
| ] | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| # Write reference gammas to file | ||||||||||
| np.savetxt( | ||||||||||
| work_dir + "gammas.txt", ref_noise_model.strength_list, header="##", fmt="%.6f" | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| propagator = PropagatorWithGradients( | ||||||||||
| sim_params=sim_params, | ||||||||||
| hamiltonian=H_0, | ||||||||||
| compact_noise_model=ref_noise_model, | ||||||||||
| init_state=init_state, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| propagator.set_observable_list(obs_list) | ||||||||||
|
|
||||||||||
| print("Computing reference trajectory ... ") | ||||||||||
| propagator.run(ref_noise_model) | ||||||||||
| ref_traj = propagator.obs_traj | ||||||||||
| print("Reference trajectory computed.") | ||||||||||
|
|
||||||||||
| # Optimizing the model | ||||||||||
| gamma_guess = 0.4 | ||||||||||
|
|
||||||||||
| sim_params.num_traj = ( | ||||||||||
| 300 # Reducing the number of trajectories for the optimization | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| guess_noise_model = CompactNoiseModel( | ||||||||||
| [ | ||||||||||
| { | ||||||||||
| "name": noise_operator, | ||||||||||
| "sites": [i for i in range(L)], | ||||||||||
| "strength": gamma_guess, | ||||||||||
| } | ||||||||||
| ] | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| opt_propagator = PropagatorWithGradients( | ||||||||||
| sim_params=sim_params, | ||||||||||
| hamiltonian=H_0, | ||||||||||
| compact_noise_model=guess_noise_model, | ||||||||||
| init_state=init_state, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| loss = LossClass( | ||||||||||
| ref_traj=ref_traj, | ||||||||||
| traj_gradients=opt_propagator, | ||||||||||
| working_dir=work_dir, | ||||||||||
| print_to_file=True, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| characterizer = Characterizer( | ||||||||||
| traj_gradients=opt_propagator, init_guess=guess_noise_model, loss=loss | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| print("Optimizing ... ") | ||||||||||
| characterizer.adam_optimize(max_iterations=50) | ||||||||||
| print("Optimization completed.") | ||||||||||
|
Comment on lines
+137
to
+139
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Clarify that this example uses gradient-based optimization. The PR title and objectives emphasize "Gradient-Free Noise Characterization," but this example demonstrates Consider adding a note before Line 138: Note: This example uses the Adam optimizer, which is a gradient-based method. For gradient-free optimization, you can use:
- `characterizer.cma_optimize(max_iterations=50)`
- `characterizer.mcmc_optimize(max_iterations=50)`
- `characterizer.bayesian_optimize(max_iterations=50)`🤖 Prompt for AI Agents |
||||||||||
| ``` | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,8 +29,6 @@ classifiers = [ | |
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Python :: 3.13", | ||
| "Programming Language :: Python :: 3.14", | ||
| "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", | ||
| "Typing :: Typed", | ||
| ] | ||
|
|
@@ -49,6 +47,16 @@ dependencies = [ | |
| "qiskit>=1.3.0; python_version >= '3.13'", | ||
| "opt-einsum>=3.4.0", | ||
| "tqdm>=4.67.1", | ||
| "cma>=4.0.0", | ||
|
|
||
| "torch>=2.1.0; python_version < '3.12'", | ||
| "torch>=2.4.0; python_version >= '3.12' and python_version < '3.13'", | ||
|
|
||
|
|
||
| "botorch>=0.16.0; python_version < '3.13'", | ||
| "gpytorch>=1.14.2; python_version < '3.13'", | ||
|
Comment on lines
+50
to
+57
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, find the pyproject.toml file in the repository
find . -name "pyproject.toml" -type f | head -5Repository: munich-quantum-toolkit/yaqs Length of output: 87 🏁 Script executed: # Read the pyproject.toml file to verify the dependency markers and requires-python
cat -n ./pyproject.tomlRepository: munich-quantum-toolkit/yaqs Length of output: 7179 🏁 Script executed: # Check if torch, botorch, gpytorch are imported anywhere in the source code
find src -name "*.py" -type f | head -20Repository: munich-quantum-toolkit/yaqs Length of output: 906 🏁 Script executed: # Search for imports of torch, botorch, and gpytorch
rg "import torch|from torch|import botorch|from botorch|import gpytorch|from gpytorch" src/ --type pyRepository: munich-quantum-toolkit/yaqs Length of output: 870 🏁 Script executed: # Check the noise_char module to see if torch/botorch/gpytorch imports are guarded
cat -n src/mqt/yaqs/noise_char/optimization_algorithms/gradient_free/bayesian.py | head -50Repository: munich-quantum-toolkit/yaqs Length of output: 1988 🏁 Script executed: # Check if there's a guard around the imports in the noise_char module's __init__.py
find src/mqt/yaqs/noise_char -name "__init__.py" | xargs cat -nRepository: munich-quantum-toolkit/yaqs Length of output: 1230 🏁 Script executed: # Find the actual noise_char __init__.py and check imports
find src/mqt/yaqs/noise_char -type f -name "*.py" | xargs ls -laRepository: munich-quantum-toolkit/yaqs Length of output: 1261 🏁 Script executed: # Check the noise_char __init__.py to see what's exposed
cat -n src/mqt/yaqs/noise_char/__init__.pyRepository: munich-quantum-toolkit/yaqs Length of output: 360 🏁 Script executed: # Check the characterizer.py to see if it imports bayesian directly
cat -n src/mqt/yaqs/noise_char/characterizer.py | head -80Repository: munich-quantum-toolkit/yaqs Length of output: 3266 🏁 Script executed: # Check if the imports in characterizer.py are guarded, and check where bayesian_opt is called
cat -n src/mqt/yaqs/noise_char/characterizer.py | grep -A 5 -B 5 "bayesian_opt"Repository: munich-quantum-toolkit/yaqs Length of output: 1429 🏁 Script executed: # Check if there are any conditional/try-except imports around torch/botorch/gpytorch
rg "try:|except|ImportError" src/mqt/yaqs/noise_char/optimization_algorithms/gradient_free/bayesian.py -B 2 -A 2Repository: munich-quantum-toolkit/yaqs Length of output: 53 🏁 Script executed: # Verify that the imports at the top of bayesian.py are not guarded
head -35 src/mqt/yaqs/noise_char/optimization_algorithms/gradient_free/bayesian.pyRepository: munich-quantum-toolkit/yaqs Length of output: 1115 Align Python version support: either cap requires-python to <3.13 or add conditional imports for optimization dependencies.
Either:
🤖 Prompt for AI Agents |
||
| "pyro-ppl>=1.9.0; python_version < '3.13'", | ||
|
|
||
| "threadpoolctl>=3.1.0", | ||
| "numba>=0.61.0", | ||
| "numba>=0.63.0; python_version >= '3.14'", | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import numpy as np | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from scipy.stats import truncnorm | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from ..libraries.gate_library import GateLibrary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from ..libraries.noise_library import NoiseLibrary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -262,3 +263,89 @@ def get_operator(name: str) -> NDArray[np.complex128]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| operator: BaseGate = operator_class() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return operator.matrix | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class CompactNoiseModel: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """A class to represent a compact noise model with multi-site noise processes.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, compact_processes: list[dict[str, Any]] | None = None) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Initialize the compact noise model. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parameters. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ---------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| compact_processes : list[dict[str, Any]] | None, optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A list of compact noise process specifications or None. Each process dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| must contain the following keys: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - "name" (str): name of a noise process available from GateLibrary. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - "sites" (iterable[int]): indices of sites the compact process acts on. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - "strength" (numeric): strength/amplitude of the noise process. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Behavior | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - If compact_processes is provided, a deep copy is stored in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.compact_processes to avoid external mutation; otherwise an empty list | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is used. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Each process dict is validated: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Must contain the keys "name", "sites", and "strength". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The GateLibrary entry for the given "name" must exist and represent a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1-site interaction (GateLibrary.<name>().interaction == 1). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Violations raise AssertionError or ValueError. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The compact processes are expanded into single-site process entries: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - For each site in a compact process, an expanded dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {"name": name, "sites": [site], "strength": strength} is appended to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_processes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - For each expanded entry, the index of the originating compact process | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is appended to self.index_list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - A NoiseModel is created from the expanded processes and stored as | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_noise_model. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Attributes set | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.compact_processes : list[dict[str, Any]] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Deep-copied list of compact process definitions (or empty list). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_processes : list[dict[str, Any]] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List of per-site expanded process dictionaries. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.index_list : list[int] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Mapping from each expanded process to the index of its original compact | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process in self.compact_processes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_noise_model : NoiseModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NoiseModel constructed from self.expanded_processes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.strength_list : np.ndarray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Array of strengths corresponding to each compact process. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Raises: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ------ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ValueError: If the named gate is not found in GateLibrary. The exception message is: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Gate '<name>' not found in GateLibrary". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ----- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - This initializer assumes GateLibrary and NoiseModel are available in the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| surrounding module scope. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The method performs input validation and expansion to ensure downstream | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| code can work with single-site noise process descriptions. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.compact_processes: list[dict[str, Any]] = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy.deepcopy(compact_processes) if compact_processes is not None else [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_processes: list[dict[str, Any]] = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.index_list: list[int] = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i, proc in enumerate(self.compact_processes): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "name" in proc, "Each process must have a 'name' key" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name = proc["name"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not hasattr(GateLibrary, name): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = f"Gate '{name}' not found in GateLibrary" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = "Only 1-site noise processes are supported in CompactNoiseModel" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert getattr(GateLibrary, name)().interaction == 1, msg | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "sites" in proc, "Each process must have a 'sites' key" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "strength" in proc, "Each process must have a 'strength' key" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for site in proc["sites"]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_processes.append({"name": proc["name"], "sites": [site], "strength": proc["strength"]}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.index_list.append(i) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+334
to
+347
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Validation order could be optimized to fail fast. Currently, the code validates Proposed reordering for fail-fast validation for i, proc in enumerate(self.compact_processes):
assert "name" in proc, "Each process must have a 'name' key"
+ assert "sites" in proc, "Each process must have a 'sites' key"
+ assert "strength" in proc, "Each process must have a 'strength' key"
name = proc["name"]
if not hasattr(GateLibrary, name):
msg = f"Gate '{name}' not found in GateLibrary"
raise ValueError(msg)
msg = "Only 1-site noise processes are supported in CompactNoiseModel"
assert getattr(GateLibrary, name)().interaction == 1, msg
- assert "sites" in proc, "Each process must have a 'sites' key"
- assert "strength" in proc, "Each process must have a 'strength' key"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.strength_list: np.ndarray = np.array([proc["strength"] for proc in self.compact_processes]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.expanded_noise_model: NoiseModel = NoiseModel(self.expanded_processes) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Copyright (c) 2025 - 2026 Chair for Design Automation, TUM | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| # | ||
| # Licensed under the MIT License | ||
|
|
||
| """This module contains the optimization routines for noise characterization.""" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Docstring scope is incomplete. The module docstring describes only "optimization routines," but per the PR context, this module provides a comprehensive noise characterization subsystem including propagators, loss evaluators, a high-level Characterizer orchestrator, and multiple optimization strategies (both gradient-based and gradient-free). Consider revising the docstring to reflect the broader scope. 🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: munich-quantum-toolkit/yaqs
Length of output: 8425
Fix incorrect import paths on lines 19-21.
The imports contain two errors:
LossClassshould be imported frommqt.yaqs.noise_char.loss, not from a non-existentmqt.yaqs.noise_char.optimizationmodule.PropagatorWithGradientsdoes not exist; the correct class isPropagatorfrommqt.yaqs.noise_char.propagation.Correct imports should be:
🤖 Prompt for AI Agents