qadence 1.5.2__py3-none-any.whl → 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. qadence/__init__.py +33 -5
  2. qadence/backend.py +2 -2
  3. qadence/backends/adjoint.py +8 -4
  4. qadence/backends/braket/backend.py +3 -2
  5. qadence/backends/braket/config.py +2 -2
  6. qadence/backends/gpsr.py +1 -1
  7. qadence/backends/horqrux/backend.py +4 -0
  8. qadence/backends/horqrux/config.py +2 -2
  9. qadence/backends/pulser/backend.py +71 -45
  10. qadence/backends/pulser/config.py +0 -28
  11. qadence/backends/pulser/pulses.py +2 -2
  12. qadence/backends/pyqtorch/backend.py +3 -2
  13. qadence/backends/pyqtorch/config.py +2 -2
  14. qadence/blocks/block_to_tensor.py +4 -4
  15. qadence/blocks/matrix.py +2 -2
  16. qadence/blocks/utils.py +2 -2
  17. qadence/circuit.py +5 -2
  18. qadence/constructors/__init__.py +1 -10
  19. qadence/constructors/ansatze.py +1 -65
  20. qadence/constructors/daqc/daqc.py +3 -2
  21. qadence/constructors/daqc/gen_parser.py +3 -2
  22. qadence/constructors/daqc/utils.py +3 -3
  23. qadence/constructors/feature_maps.py +2 -90
  24. qadence/constructors/hamiltonians.py +2 -6
  25. qadence/constructors/rydberg_feature_maps.py +2 -2
  26. qadence/decompose.py +2 -2
  27. qadence/engines/torch/differentiable_expectation.py +7 -0
  28. qadence/extensions.py +4 -15
  29. qadence/log_config.yaml +24 -0
  30. qadence/logger.py +9 -27
  31. qadence/ml_tools/models.py +10 -2
  32. qadence/ml_tools/saveload.py +14 -5
  33. qadence/ml_tools/train_grad.py +3 -3
  34. qadence/ml_tools/train_no_grad.py +2 -2
  35. qadence/models/quantum_model.py +13 -6
  36. qadence/noise/readout.py +2 -3
  37. qadence/operations/__init__.py +0 -2
  38. qadence/operations/analog.py +2 -12
  39. qadence/operations/control_ops.py +3 -2
  40. qadence/operations/ham_evo.py +2 -2
  41. qadence/operations/parametric.py +3 -2
  42. qadence/operations/primitive.py +2 -2
  43. qadence/parameters.py +2 -2
  44. qadence/serialization.py +2 -2
  45. qadence/transpile/block.py +2 -2
  46. qadence/types.py +2 -2
  47. qadence/utils.py +2 -2
  48. {qadence-1.5.2.dist-info → qadence-1.6.0.dist-info}/METADATA +16 -8
  49. {qadence-1.5.2.dist-info → qadence-1.6.0.dist-info}/RECORD +51 -50
  50. {qadence-1.5.2.dist-info → qadence-1.6.0.dist-info}/WHEEL +0 -0
  51. {qadence-1.5.2.dist-info → qadence-1.6.0.dist-info}/licenses/LICENSE +0 -0
qadence/__init__.py CHANGED
@@ -1,10 +1,43 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
4
+ import logging.config
5
+ import os
3
6
  from importlib import import_module
7
+ from pathlib import Path
4
8
 
9
+ import yaml
5
10
  from torch import cdouble, set_default_dtype
6
11
  from torch import float64 as torchfloat64
7
12
 
13
+ DEFAULT_FLOAT_DTYPE = torchfloat64
14
+ DEFAULT_COMPLEX_DTYPE = cdouble
15
+ set_default_dtype(DEFAULT_FLOAT_DTYPE)
16
+
17
+ logging_levels = {
18
+ "DEBUG": logging.DEBUG,
19
+ "INFO": logging.INFO,
20
+ "WARNING": logging.WARNING,
21
+ "ERROR": logging.ERROR,
22
+ "CRITICAL": logging.CRITICAL,
23
+ }
24
+ LOG_CONFIG_PATH = os.environ.get("QADENCE_LOG_CONFIG", f"{Path(__file__).parent}/log_config.yaml")
25
+ LOG_BASE_LEVEL = os.environ.get("QADENCE_LOG_LEVEL", "").upper()
26
+
27
+ with open(LOG_CONFIG_PATH, "r") as stream:
28
+ log_config = yaml.load(stream, Loader=yaml.FullLoader)
29
+ logging.config.dictConfig(log_config)
30
+
31
+ logger: logging.Logger = logging.getLogger(__name__)
32
+ LOG_LEVEL = logging_levels.get(LOG_BASE_LEVEL, logging.INFO) # type: ignore[arg-type]
33
+ logger.setLevel(LOG_LEVEL)
34
+ [
35
+ h.setLevel(LOG_LEVEL) # type: ignore[func-returns-value]
36
+ for h in logger.handlers
37
+ if h.get_name() == "console"
38
+ ]
39
+ logger.debug(f"Qadence logger successfully setup with log level {LOG_LEVEL}")
40
+
8
41
  from .analog import *
9
42
  from .backend import *
10
43
  from .backends import *
@@ -28,11 +61,6 @@ from .transpile import *
28
61
  from .types import *
29
62
  from .utils import *
30
63
 
31
- DEFAULT_FLOAT_DTYPE = torchfloat64
32
- DEFAULT_COMPLEX_DTYPE = cdouble
33
- set_default_dtype(DEFAULT_FLOAT_DTYPE)
34
-
35
-
36
64
  """Fetch the functions defined in the __all__ of each sub-module.
37
65
 
38
66
  Import to the qadence name space. Make sure each added submodule has the respective definition:
qadence/backend.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from abc import ABC, abstractmethod
4
4
  from collections import Counter
5
5
  from dataclasses import dataclass, fields
6
+ from logging import getLogger
6
7
  from typing import Any, Callable, Iterator, Tuple
7
8
 
8
9
  from openfermion import QubitOperator
@@ -20,14 +21,13 @@ from qadence.blocks import (
20
21
  )
21
22
  from qadence.blocks.analog import ConstantAnalogRotation, InteractionBlock
22
23
  from qadence.circuit import QuantumCircuit
23
- from qadence.logger import get_logger
24
24
  from qadence.measurements import Measurements
25
25
  from qadence.mitigations import Mitigations
26
26
  from qadence.noise import Noise
27
27
  from qadence.parameters import stringify
28
28
  from qadence.types import ArrayLike, BackendName, DiffMode, Endianness, Engine, ParamDictType
29
29
 
30
- logger = get_logger(__file__)
30
+ logger = getLogger(__name__)
31
31
 
32
32
 
33
33
  @dataclass
@@ -7,7 +7,7 @@ from pyqtorch.circuit import QuantumCircuit as PyQCircuit
7
7
  from pyqtorch.parametric import Parametric as PyQParametric
8
8
  from pyqtorch.primitive import Primitive as PyQPrimitive
9
9
  from pyqtorch.utils import inner_prod, param_dict
10
- from torch import Tensor, no_grad, tensor
10
+ from torch import Tensor, no_grad, zeros
11
11
  from torch.autograd import Function
12
12
  from torch.nn import Module
13
13
 
@@ -125,7 +125,7 @@ class AdjointExpectation(Function):
125
125
  ctx.projected_state, op.dagger(values), op.qubit_support
126
126
  )
127
127
  elif isinstance(op, PyQCircuit):
128
- grads = [g for sub_op in op.reverse() for g in _apply_adjoint(ctx, sub_op)]
128
+ grads = [g for sub_op in op.operations[::-1] for g in _apply_adjoint(ctx, sub_op)]
129
129
  elif isinstance(op, PyQPrimitive):
130
130
  ctx.out_state = apply_operator(ctx.out_state, op.dagger(values), op.qubit_support)
131
131
  if isinstance(op, PyQParametric) and values[op.param_name].requires_grad:
@@ -147,13 +147,17 @@ class AdjointExpectation(Function):
147
147
 
148
148
  grads = list(
149
149
  reversed(
150
- [grad_out * g for op in ctx.circuit.reverse() for g in _apply_adjoint(ctx, op)]
150
+ [
151
+ grad_out * g
152
+ for op in ctx.circuit.operations[::-1]
153
+ for g in _apply_adjoint(ctx, op)
154
+ ]
151
155
  )
152
156
  )
153
157
  num_grads = len(grads)
154
158
  num_params = len(ctx.saved_tensors)
155
159
  diff = num_params - num_grads
156
- grads = grads + [tensor([0]) for _ in range(diff)]
160
+ grads = grads + [zeros(1, device=ctx.circuit.device) for _ in range(diff)]
157
161
  # Set observable grads to 0
158
162
  ctx.save_for_backward(*grads)
159
163
  return (None, None, None, None, *grads)
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
4
  from dataclasses import dataclass, field
5
+ from logging import getLogger
5
6
  from typing import Any
6
7
 
7
8
  import numpy as np
@@ -15,7 +16,6 @@ from qadence.backend import ConvertedCircuit, ConvertedObservable
15
16
  from qadence.backends.utils import to_list_of_dicts
16
17
  from qadence.blocks import AbstractBlock, block_to_tensor
17
18
  from qadence.circuit import QuantumCircuit
18
- from qadence.logger import get_logger
19
19
  from qadence.measurements import Measurements
20
20
  from qadence.mitigations import Mitigations
21
21
  from qadence.mitigations.protocols import apply_mitigation
@@ -29,7 +29,7 @@ from qadence.utils import Endianness
29
29
  from .config import Configuration, default_passes
30
30
  from .convert_ops import convert_block
31
31
 
32
- logger = get_logger(__file__)
32
+ logger = getLogger(__name__)
33
33
 
34
34
 
35
35
  def promote_parameters(parameters: dict[str, Tensor | float]) -> dict[str, float]:
@@ -56,6 +56,7 @@ class Backend(BackendInterface):
56
56
  native_endianness: Endianness = Endianness.BIG
57
57
  config: Configuration = field(default_factory=Configuration)
58
58
  engine: Engine = Engine.TORCH
59
+ logger.debug("Initialised")
59
60
 
60
61
  # braket specifics
61
62
  # TODO: include it in the configuration?
@@ -1,13 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
+ from logging import getLogger
4
5
  from typing import Callable
5
6
 
6
7
  from qadence.backend import BackendConfiguration
7
- from qadence.logger import get_logger
8
8
  from qadence.transpile import digitalize, fill_identities
9
9
 
10
- logger = get_logger(__name__)
10
+ logger = getLogger(__name__)
11
11
 
12
12
  default_passes: list[Callable] = [fill_identities, digitalize]
13
13
 
qadence/backends/gpsr.py CHANGED
@@ -20,7 +20,7 @@ def general_psr(spectrum: Tensor, n_eqs: int | None = None, shift_prefac: float
20
20
  sorted_unique_spectral_gaps = torch.tensor(list(sorted_unique_spectral_gaps))
21
21
 
22
22
  if n_eqs == 1:
23
- return partial(single_gap_psr, spectral_gap=sorted_unique_spectral_gaps.item())
23
+ return single_gap_psr
24
24
  else:
25
25
  return partial(
26
26
  multi_gap_psr,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
4
  from dataclasses import dataclass, field
5
+ from logging import getLogger
5
6
  from typing import Any
6
7
 
7
8
  import jax
@@ -28,6 +29,8 @@ from qadence.utils import int_to_basis
28
29
  from .config import Configuration, default_passes
29
30
  from .convert_ops import HorqruxCircuit, convert_block, convert_observable
30
31
 
32
+ logger = getLogger(__name__)
33
+
31
34
 
32
35
  @dataclass(frozen=True, eq=True)
33
36
  class Backend(BackendInterface):
@@ -43,6 +46,7 @@ class Backend(BackendInterface):
43
46
  native_endianness: Endianness = Endianness.BIG
44
47
  config: Configuration = field(default_factory=Configuration)
45
48
  engine: Engine = Engine.JAX
49
+ logger.debug("Initialised")
46
50
 
47
51
  def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
48
52
  passes = self.config.transpilation_passes
@@ -1,18 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
+ from logging import getLogger
4
5
  from typing import Callable
5
6
 
6
7
  from qadence.analog import add_background_hamiltonian
7
8
  from qadence.backend import BackendConfiguration
8
- from qadence.logger import get_logger
9
9
  from qadence.transpile import (
10
10
  blockfn_to_circfn,
11
11
  flatten,
12
12
  scale_primitive_blocks_only,
13
13
  )
14
14
 
15
- logger = get_logger(__name__)
15
+ logger = getLogger(__name__)
16
16
 
17
17
 
18
18
  def default_passes(config: Configuration) -> list[Callable]:
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
+ from collections.abc import Iterable
4
5
  from dataclasses import dataclass, field
6
+ from logging import getLogger
5
7
  from typing import Any
6
8
 
7
9
  import numpy as np
@@ -10,7 +12,7 @@ import torch
10
12
  from pulser import Register as PulserRegister
11
13
  from pulser import Sequence
12
14
  from pulser_simulation import SimConfig
13
- from pulser_simulation.simresults import SimulationResults
15
+ from pulser_simulation.simresults import CoherentResults, SimulationResults
14
16
  from pulser_simulation.simulation import QutipEmulator
15
17
  from torch import Tensor
16
18
 
@@ -19,7 +21,6 @@ from qadence.backend import ConvertedCircuit, ConvertedObservable
19
21
  from qadence.backends.utils import to_list_of_dicts
20
22
  from qadence.blocks import AbstractBlock
21
23
  from qadence.circuit import QuantumCircuit
22
- from qadence.logger import get_logger
23
24
  from qadence.measurements import Measurements
24
25
  from qadence.mitigations import Mitigations
25
26
  from qadence.mitigations.protocols import apply_mitigation
@@ -37,7 +38,7 @@ from .convert_ops import convert_observable
37
38
  from .devices import IdealDevice, RealisticDevice
38
39
  from .pulses import add_addressing_pattern, add_pulses
39
40
 
40
- logger = get_logger(__file__)
41
+ logger = getLogger(__name__)
41
42
 
42
43
 
43
44
  def _convert_init_state(state: Tensor) -> np.ndarray:
@@ -70,27 +71,6 @@ def make_sequence(circ: QuantumCircuit, config: Configuration) -> Sequence:
70
71
  f"Specified device of type {device_specs.type} is not supported by the pulser backend."
71
72
  )
72
73
 
73
- ########
74
- # FIXME: Remove the block below in V1.5.0
75
- if config.spacing is not None:
76
- logger.warning(
77
- "Passing register spacing in the backend configuration is deprecated. "
78
- "Please pass it in the register directly, as detailed in the register tutorial."
79
- )
80
- # Rescales the register coordinates, as was done with the previous "spacing" argument.
81
- qadence_register = qadence_register.rescale_coords(scaling=config.spacing)
82
- else:
83
- if qadence_register.min_distance < 4.0:
84
- # Throws warning for minimum distance below 4 because the typical values used
85
- # for the standard pulser device parameters is ~7-8, so this likely means the user
86
- # forgot to set the spacing at register creation.
87
- logger.warning(
88
- "Register with distance between atoms smaller than 4µm detected. "
89
- "Pulser backend no longer has a default spacing of 8µm applied to the register. "
90
- "Make sure you set the desired spacing as detailed in the register tutorial."
91
- )
92
- ########
93
-
94
74
  pulser_register = create_register(qadence_register)
95
75
 
96
76
  sequence = Sequence(pulser_register, device)
@@ -160,6 +140,7 @@ class Backend(BackendInterface):
160
140
  native_endianness: Endianness = Endianness.BIG
161
141
  config: Configuration = field(default_factory=Configuration)
162
142
  engine: Engine = Engine.TORCH
143
+ logger.debug("Initialised")
163
144
 
164
145
  def circuit(self, circ: QuantumCircuit) -> Sequence:
165
146
  passes = self.config.transpilation_passes
@@ -250,30 +231,49 @@ class Backend(BackendInterface):
250
231
  self,
251
232
  circuit: ConvertedCircuit,
252
233
  noise: Noise,
253
- param_values: dict[str, Tensor] = {},
234
+ param_values: dict[str, Tensor] = dict(),
254
235
  state: Tensor | None = None,
255
236
  endianness: Endianness = Endianness.BIG,
256
- ) -> list:
237
+ ) -> Tensor:
257
238
  vals = to_list_of_dicts(param_values)
258
239
  noise_probs = noise.options.get("noise_probs", None)
259
240
  if noise_probs is None:
260
- KeyError(f"A range of noise probabilies should be passed. Got {noise_probs}.")
261
-
262
- noisy_batched_dm = []
241
+ KeyError("A `noise probs` option should be passed to the <class QuantumModel>.")
242
+ if not (isinstance(noise_probs, float) or isinstance(noise_probs, Iterable)):
243
+ KeyError(
244
+ "A single or a range of noise probabilities"
245
+ " should be passed. Got {type(noise_probs)}."
246
+ )
263
247
 
264
- # Pulser requires numpy types.
265
- for noise_prob in noise_probs.numpy():
266
- batched_dm = []
267
- sim_config = {"noise": noise.protocol, noise.protocol + "_prob": noise_prob}
248
+ def run_noisy_sim(noise_prob: float) -> Tensor:
249
+ batched_dm = np.zeros(
250
+ (len(vals), 2**circuit.abstract.n_qubits, 2**circuit.abstract.n_qubits),
251
+ dtype=np.complex128,
252
+ )
253
+ sim_config = {"noise": noise.protocol, noise.protocol + "_rate": noise_prob}
268
254
  self.config.sim_config = SimConfig(**sim_config)
269
255
 
270
256
  for i, param_values_el in enumerate(vals):
271
257
  sequence = self.assign_parameters(circuit, param_values_el)
272
- sim_result = simulate_sequence(sequence, self.config, state)
273
- batched_dm.append(sim_result)
274
- noisy_batched_dm.append(batched_dm)
258
+ sim_result: CoherentResults = simulate_sequence(sequence, self.config, state)
259
+ final_state = sim_result.get_final_state().data.toarray()
260
+ batched_dm[i] = np.flip(final_state)
261
+ return torch.from_numpy(batched_dm)
275
262
 
276
- return noisy_batched_dm
263
+ # Pulser requires numpy types.
264
+ if isinstance(noise_probs, Iterable):
265
+ noisy_batched_dms = []
266
+ for noise_prob in noise_probs:
267
+ noisy_batched_dms.append(run_noisy_sim(noise_prob))
268
+ noisy_batched_dms = torch.stack(noisy_batched_dms)
269
+ else:
270
+ noisy_batched_dms = run_noisy_sim(noise_probs)
271
+
272
+ if endianness != self.native_endianness:
273
+ from qadence.transpile import invert_endianness
274
+
275
+ noisy_batched_dms = invert_endianness(noisy_batched_dms)
276
+ return noisy_batched_dms
277
277
 
278
278
  def sample(
279
279
  self,
@@ -327,14 +327,40 @@ class Backend(BackendInterface):
327
327
  ) -> Tensor:
328
328
  observable = observable if isinstance(observable, list) else [observable]
329
329
  if mitigation is None:
330
- state = self.run(circuit, param_values=param_values, state=state, endianness=endianness)
331
- support = sorted(list(circuit.abstract.register.support))
332
- res_list = [
333
- obs.native(state, param_values, qubit_support=support) for obs in observable
334
- ]
335
- res = torch.transpose(torch.stack(res_list), 0, 1)
336
- res = res if len(res.shape) > 0 else res.reshape(1)
337
- return res.real
330
+ if noise is None:
331
+ state = self.run(
332
+ circuit, param_values=param_values, state=state, endianness=endianness
333
+ )
334
+ support = sorted(list(circuit.abstract.register.support))
335
+ res_list = [
336
+ obs.native(state, param_values, qubit_support=support) for obs in observable
337
+ ]
338
+ res = torch.transpose(torch.stack(res_list), 0, 1)
339
+ res = res if len(res.shape) > 0 else res.reshape(1)
340
+ return res.real
341
+ elif noise is not None:
342
+ dms = self.run_dm(
343
+ circuit=circuit,
344
+ noise=noise,
345
+ param_values=param_values,
346
+ state=state,
347
+ endianness=endianness,
348
+ )
349
+ support = sorted(list(circuit.abstract.register.support))
350
+ # TODO: There should be a better check for batched density matrices.
351
+ if dms.size()[0] > 1:
352
+ res_list = [
353
+ [obs.native(dm, param_values, qubit_support=support) for dm in dms]
354
+ for obs in observable
355
+ ]
356
+ res = torch.stack([torch.transpose(torch.stack(res), 0, 1) for res in res_list])
357
+ else:
358
+ res_list = [
359
+ obs.native(dms, param_values, qubit_support=support) for obs in observable
360
+ ]
361
+ res = torch.transpose(torch.stack(res_list), 0, 1)
362
+ res = res if len(res.shape) > 0 else res.reshape(1)
363
+ return res.real
338
364
  elif mitigation is not None:
339
365
  logger.warning(
340
366
  "Mitigation protocol is deprecated. Use qadence-protocols instead.",
@@ -8,7 +8,6 @@ from pasqal_cloud.device import EmulatorType
8
8
  from pulser_simulation.simconfig import SimConfig
9
9
 
10
10
  from qadence.backend import BackendConfiguration
11
- from qadence.types import DeviceType, Interaction
12
11
 
13
12
  DEFAULT_CLOUD_ENV = "prod"
14
13
 
@@ -25,14 +24,6 @@ class CloudConfiguration:
25
24
 
26
25
  @dataclass
27
26
  class Configuration(BackendConfiguration):
28
- device_type: DeviceType = DeviceType.IDEALIZED
29
- """The type of quantum Device to use in the simulations.
30
-
31
- FIXME: This is deprecated, the device_type is now controlled in the
32
- Qadence Device, as detailed in the documentation.
33
- FIXME: Remove in v1.5.0
34
- """
35
-
36
27
  sampling_rate: float = 1.0
37
28
  """Sampling rate to be used for local simulations.
38
29
 
@@ -40,14 +31,6 @@ class Configuration(BackendConfiguration):
40
31
  to avoid any interpolation in the solving procedure
41
32
  """
42
33
 
43
- spacing: Optional[float] = None
44
- """Spacing that multiplies the coordinates of the register.
45
-
46
- FIXME: This is deprecated, spacing is now controlled in the Register,
47
- as detailed in the register tutorial.
48
- FIXME: Remove in v1.5.0
49
- """
50
-
51
34
  method_solv: str = "adams"
52
35
  """Solver method to pass to the Qutip solver."""
53
36
 
@@ -83,17 +66,6 @@ class Configuration(BackendConfiguration):
83
66
  FIXME: To be deprecated.
84
67
  """
85
68
 
86
- interaction: Interaction = Interaction.NN
87
- """Type of interaction introduced in the Hamiltonian.
88
-
89
- Currently, only
90
- NN interaction is support. XY interaction is possible but not implemented
91
-
92
- FIXME: This is deprecated, the interaction is now controlled in the
93
- Qadence Device, as detailed in the documentation.
94
- FIXME: Remove in v1.5.0
95
- """
96
-
97
69
  # configuration for cloud simulations
98
70
  cloud_configuration: Optional[CloudConfiguration] = None
99
71
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from functools import partial
4
+ from logging import getLogger
4
5
  from typing import Union
5
6
 
6
7
  import numpy as np
@@ -20,7 +21,6 @@ from qadence.blocks.analog import (
20
21
  Interaction,
21
22
  InteractionBlock,
22
23
  )
23
- from qadence.logger import get_logger
24
24
  from qadence.operations import RX, RY, RZ, AnalogEntanglement
25
25
  from qadence.parameters import evaluate
26
26
  from qadence.types import PI, OpName
@@ -29,7 +29,7 @@ from .channels import GLOBAL_CHANNEL, LOCAL_CHANNEL
29
29
  from .config import Configuration
30
30
  from .waveforms import SquareWaveform
31
31
 
32
- logger = get_logger(__file__)
32
+ logger = getLogger(__name__)
33
33
 
34
34
  TVar = Union[Variable, VariableItem]
35
35
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
4
  from dataclasses import dataclass, field
5
+ from logging import getLogger
5
6
  from typing import Any
6
7
 
7
8
  import pyqtorch as pyq
@@ -18,7 +19,6 @@ from qadence.backends.utils import (
18
19
  )
19
20
  from qadence.blocks import AbstractBlock
20
21
  from qadence.circuit import QuantumCircuit
21
- from qadence.logger import get_logger
22
22
  from qadence.measurements import Measurements
23
23
  from qadence.mitigations.protocols import Mitigations, apply_mitigation
24
24
  from qadence.noise import Noise
@@ -36,7 +36,7 @@ from qadence.utils import infer_batchsize, int_to_basis
36
36
  from .config import Configuration, default_passes
37
37
  from .convert_ops import convert_block, convert_observable
38
38
 
39
- logger = get_logger(__name__)
39
+ logger = getLogger(__name__)
40
40
 
41
41
 
42
42
  @dataclass(frozen=True, eq=True)
@@ -53,6 +53,7 @@ class Backend(BackendInterface):
53
53
  native_endianness: Endianness = Endianness.BIG
54
54
  config: Configuration = field(default_factory=Configuration)
55
55
  engine: Engine = Engine.TORCH
56
+ logger.debug("Initialised")
56
57
 
57
58
  def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
58
59
  passes = self.config.transpilation_passes
@@ -1,11 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
+ from logging import getLogger
4
5
  from typing import Callable
5
6
 
6
7
  from qadence.analog import add_background_hamiltonian
7
8
  from qadence.backend import BackendConfiguration
8
- from qadence.logger import get_logger
9
9
  from qadence.transpile import (
10
10
  blockfn_to_circfn,
11
11
  chain_single_qubit_ops,
@@ -14,7 +14,7 @@ from qadence.transpile import (
14
14
  )
15
15
  from qadence.types import AlgoHEvo
16
16
 
17
- logger = get_logger(__name__)
17
+ logger = getLogger(__name__)
18
18
 
19
19
 
20
20
  def default_passes(config: Configuration) -> list[Callable]:
@@ -62,7 +62,7 @@ def _fill_identities(
62
62
  full_qubit_support: tuple | list,
63
63
  diag_only: bool = False,
64
64
  endianness: Endianness = Endianness.BIG,
65
- device: torch.device = torch.device("cpu"),
65
+ device: torch.device | None = None,
66
66
  ) -> torch.Tensor:
67
67
  """Returns a Kronecker product of a block matrix with identities.
68
68
 
@@ -265,7 +265,7 @@ def block_to_diagonal(
265
265
  qubit_support: tuple | list | None = None,
266
266
  use_full_support: bool = True,
267
267
  endianness: Endianness = Endianness.BIG,
268
- device: torch.device = torch.device("cpu"),
268
+ device: torch.device = None,
269
269
  ) -> torch.Tensor:
270
270
  if block.is_parametric:
271
271
  raise TypeError("Sparse observables cant be parametric.")
@@ -310,7 +310,7 @@ def block_to_tensor(
310
310
  use_full_support: bool = True,
311
311
  tensor_type: TensorType = TensorType.DENSE,
312
312
  endianness: Endianness = Endianness.BIG,
313
- device: torch.device = torch.device("cpu"),
313
+ device: torch.device = None,
314
314
  ) -> torch.Tensor:
315
315
  """
316
316
  Convert a block into a torch tensor.
@@ -369,7 +369,7 @@ def _block_to_tensor_embedded(
369
369
  qubit_support: tuple | None = None,
370
370
  use_full_support: bool = True,
371
371
  endianness: Endianness = Endianness.BIG,
372
- device: torch.device = torch.device("cpu"),
372
+ device: torch.device = None,
373
373
  ) -> torch.Tensor:
374
374
  from qadence.blocks import MatrixBlock
375
375
  from qadence.operations import CSWAP, SWAP, HamEvo
qadence/blocks/matrix.py CHANGED
@@ -1,15 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from functools import cached_property
4
+ from logging import getLogger
4
5
 
5
6
  import numpy as np
6
7
  import torch
7
8
  from torch.linalg import eigvals
8
9
 
9
10
  from qadence.blocks import PrimitiveBlock
10
- from qadence.logger import get_logger
11
11
 
12
- logger = get_logger(__name__)
12
+ logger = getLogger(__name__)
13
13
 
14
14
 
15
15
  class MatrixBlock(PrimitiveBlock):
qadence/blocks/utils.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import typing
4
4
  from enum import Enum
5
5
  from itertools import chain as _flatten
6
+ from logging import getLogger
6
7
  from typing import Generator, List, Type, TypeVar, Union, get_args
7
8
 
8
9
  from sympy import Array, Basic, Expr
@@ -29,10 +30,9 @@ from qadence.blocks.analog import (
29
30
  from qadence.blocks.analog import chain as analog_chain
30
31
  from qadence.blocks.analog import kron as analog_kron
31
32
  from qadence.exceptions import NotPauliBlockError
32
- from qadence.logger import get_logger
33
33
  from qadence.parameters import Parameter
34
34
 
35
- logger = get_logger(__name__)
35
+ logger = getLogger(__name__)
36
36
 
37
37
 
38
38
  TPrimitiveBlock = TypeVar("TPrimitiveBlock", bound=PrimitiveBlock)
qadence/circuit.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from itertools import chain as flatten
5
+ from logging import getLogger
5
6
  from pathlib import Path
6
7
  from typing import Iterable
7
8
 
@@ -15,6 +16,8 @@ from qadence.register import Register
15
16
  # Modules to be automatically added to the qadence namespace
16
17
  __all__ = ["QuantumCircuit"]
17
18
 
19
+ logger = getLogger(__name__)
20
+
18
21
 
19
22
  @dataclass(eq=False) # Avoid unhashability errors due to mutable attributes.
20
23
  class QuantumCircuit:
@@ -167,7 +170,7 @@ class QuantumCircuit:
167
170
  with open(path, "w") as file:
168
171
  file.write(qc_dumped)
169
172
  except Exception as e:
170
- print(f"Unable to write QuantumCircuit to disk due to {e}")
173
+ logger.error(f"Unable to write QuantumCircuit to disk due to {e}")
171
174
 
172
175
  return qc_dumped
173
176
 
@@ -199,6 +202,6 @@ class QuantumCircuit:
199
202
  loaded_dict = json.load(file)
200
203
 
201
204
  except Exception as e:
202
- print(f"Unable to load QuantumCircuit due to {e}")
205
+ logger.error(f"Unable to load QuantumCircuit due to {e}")
203
206
 
204
207
  return QuantumCircuit._from_dict(loaded_dict)