qadence 1.11.1__py3-none-any.whl → 1.11.2__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.
@@ -115,8 +115,10 @@ class CallbacksManager:
115
115
  self.add_callback("PlotMetrics", "train_end")
116
116
  # only save the last checkpoint if not checkpoint_best_only
117
117
  if not self.config.checkpoint_best_only:
118
- self.add_callback("SaveCheckpoint", "train_end")
119
- self.add_callback("WriteMetrics", "train_end")
118
+ if self.config.checkpoint_every != 0:
119
+ self.add_callback("SaveCheckpoint", "train_end")
120
+ if self.config.write_every != 0:
121
+ self.add_callback("WriteMetrics", "train_end")
120
122
 
121
123
  def add_callback(
122
124
  self, callback: str | Callback, on: str | TrainingStage, called_every: int = 1
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Callable
3
+ from typing import Any, Callable
4
4
  import numpy as np
5
5
  from sympy import Basic
6
6
 
@@ -8,7 +8,8 @@ from qadence.backend import BackendConfiguration
8
8
  from qadence.blocks import chain, kron
9
9
  from qadence.blocks.abstract import AbstractBlock
10
10
  from qadence.blocks.composite import ChainBlock, KronBlock
11
- from qadence.blocks.utils import add, tag
11
+ from qadence.blocks.utils import tag, add
12
+ from qadence.parameters import Parameter
12
13
  from qadence.circuit import QuantumCircuit
13
14
  from qadence.constructors import (
14
15
  analog_feature_map,
@@ -24,7 +25,7 @@ from qadence.constructors.hea import hea_digital, hea_sDAQC
24
25
  from qadence.constructors.iia import iia
25
26
  from qadence.measurements import Measurements
26
27
  from qadence.noise import NoiseHandler
27
- from qadence.operations import CNOT, RX, RY, I, N, Z
28
+ from qadence.operations import CNOT, RX, RY, RZ, I
28
29
  from qadence.register import Register
29
30
  from qadence.types import (
30
31
  AnsatzType,
@@ -733,7 +734,6 @@ def create_observable(
733
734
  interaction=config.interaction,
734
735
  detuning=config.detuning,
735
736
  )
736
-
737
737
  obs: AbstractBlock = add(shifting_term, detuning_hamiltonian)
738
738
 
739
739
  if isinstance(config.tag, str):
@@ -801,6 +801,7 @@ def build_qnn_from_configs(
801
801
  if isinstance(observable_config, list)
802
802
  else create_observable(register=register, config=observable_config)
803
803
  )
804
+
804
805
  ufa = QNN(
805
806
  circ,
806
807
  observable,
@@ -814,3 +815,262 @@ def build_qnn_from_configs(
814
815
  )
815
816
 
816
817
  return ufa
818
+
819
+
820
+ def _create_feature_map_qcnn(
821
+ n_qubits: int,
822
+ n_inputs: int,
823
+ fm_type: str = "Fourier",
824
+ op: Any = RX,
825
+ ) -> Any:
826
+ """
827
+ Creates a feature map (FM) by dividing qubits among inputs and applying.
828
+
829
+ the specified feature map type.
830
+
831
+ Args:
832
+ n_qubits (int): Total number of qubits.
833
+ n_inputs (int): Number of inputs.
834
+ fm_type (str): Type of feature map to use (e.g., "Fourier").
835
+ op (Any): Quantum operation to use in the feature map (e.g., RX).
836
+
837
+ Returns:
838
+ Any: The combined feature map as a kronecker product
839
+ of individual feature maps.
840
+ """
841
+ fm_temp = []
842
+ qubits_per_input = n_qubits // n_inputs # Base number of qubits per input
843
+ exceeding_qubits = n_qubits % n_inputs # Number of exceeding qubits
844
+ start = 0 # Track current qubit index
845
+
846
+ for i in range(n_inputs):
847
+ # Assign base qubits + 1 extra if input has exceeding qubits
848
+ num_qubits = qubits_per_input + 1 if i < exceeding_qubits else qubits_per_input
849
+ end = start + num_qubits
850
+
851
+ # Create FM for this input
852
+ fm_temp.append(
853
+ feature_map(
854
+ n_qubits=num_qubits,
855
+ param=f"\u03C6_{i}", # Use phi_i as the parameter
856
+ op=op,
857
+ fm_type=fm_type,
858
+ support=tuple(range(start, end)),
859
+ )
860
+ )
861
+ start = end # Update starting index for next FM
862
+
863
+ # Combine all feature maps using kronecker product
864
+ return kron(*fm_temp)
865
+
866
+
867
+ def _get_block_params(
868
+ params: dict,
869
+ layer: int,
870
+ rep: int,
871
+ pos: int,
872
+ is_corr: bool = False,
873
+ ) -> Any:
874
+ """
875
+ Retrieves the parameter for a given operation.
876
+
877
+ Args:
878
+ params (dict): Dictionary to store and retrieve parameters.
879
+ layer (int): The index of the current layer.
880
+ rep (int): The index of the current repetition in the layer.
881
+ pos (int): Position of the qubit in the layer.
882
+ is_corr (bool): If True, uses correlated parameters for corresponding gates in W^opt_ij.
883
+
884
+ Returns:
885
+ Parameter: the retrieved parameter.
886
+ """
887
+ if is_corr:
888
+ # Cycle pos from 0 to 8
889
+ key = f"θ_{layer}_{pos % 9}"
890
+ else:
891
+ key = f"θ_{layer}_{rep}_{pos}"
892
+
893
+ if key not in params:
894
+ params[key] = Parameter(key)
895
+ return params[key]
896
+
897
+
898
+ def _create_single_W(
899
+ params: dict,
900
+ operations: list[Any],
901
+ entangler: Any,
902
+ layer: int,
903
+ rep: int,
904
+ max_reps: int,
905
+ control: int,
906
+ target: int,
907
+ spacing: int,
908
+ n_qubits: int,
909
+ is_corr: bool = False,
910
+ ) -> ChainBlock:
911
+ """Creates a single convolutional cell W_ij."""
912
+ pad = [
913
+ I(q)
914
+ for q in range(control - spacing, control + spacing + 1)
915
+ if q != control and q != target and 0 <= q < n_qubits
916
+ ]
917
+ gates = []
918
+
919
+ # Track per-layer repetition index for proper parameter continuity
920
+ key_param_counter = f"param_index_{layer}_{rep}"
921
+ if key_param_counter not in params:
922
+ params[key_param_counter] = 0 # Initialize if first time
923
+
924
+ param_index = params[key_param_counter] # Load index
925
+ single_params = {} # Store params for single RZ/RY gates
926
+
927
+ # Apply the first sequence of operations
928
+ for _, op in enumerate(operations):
929
+ param_control = _get_block_params(params, layer, rep, param_index, is_corr)
930
+ param_index += 1
931
+ param_target = _get_block_params(params, layer, rep, param_index, is_corr)
932
+ param_index += 1
933
+ gates.append(
934
+ kron(
935
+ *pad,
936
+ op(control, param_control),
937
+ op(target, param_target),
938
+ )
939
+ )
940
+ # entangling gate
941
+ gates.append(entangler(target, control))
942
+
943
+ # Apply RZ, RY and entangling gates for intermediate step
944
+ single_params["control_rz"] = _get_block_params(params, layer, rep, param_index, is_corr)
945
+ param_index += 1
946
+ single_params["target_ry"] = _get_block_params(params, layer, rep, param_index, is_corr)
947
+ param_index += 1
948
+ gates.append(
949
+ kron(
950
+ *pad,
951
+ RZ(control, single_params["control_rz"]),
952
+ RY(target, single_params["target_ry"]),
953
+ )
954
+ )
955
+ # entangling gate
956
+ gates.append(entangler(control, target))
957
+
958
+ intermediate_ry = _get_block_params(params, layer, rep, param_index, is_corr)
959
+ param_index += 1
960
+ gates.append(
961
+ kron(
962
+ *pad,
963
+ I(control),
964
+ RY(target, intermediate_ry),
965
+ )
966
+ )
967
+ # entangling gate
968
+ gates.append(entangler(target, control))
969
+
970
+ # Apply the first sequence of operations
971
+ for _, op in enumerate(operations):
972
+ param_control = _get_block_params(params, layer, rep, param_index, is_corr)
973
+ param_index += 1
974
+ param_target = _get_block_params(params, layer, rep, param_index, is_corr)
975
+ param_index += 1
976
+ gates.append(
977
+ kron(
978
+ *pad,
979
+ op(control, param_control),
980
+ op(target, param_target),
981
+ )
982
+ )
983
+ # Add final entangling gate (control -> target)
984
+ if rep == int(max_reps - 1):
985
+ gates.append(entangler(control, target))
986
+
987
+ # Update params dict with the last used index
988
+ params[key_param_counter] = param_index
989
+
990
+ return chain(*gates)
991
+
992
+
993
+ def _create_conv_layer(
994
+ layer_index: int,
995
+ max_reps: int,
996
+ current_indices: list[int],
997
+ params: dict,
998
+ operations: list[Any],
999
+ entangler: Any,
1000
+ n_qubits: int,
1001
+ is_corr: bool,
1002
+ ) -> tuple[AbstractBlock, list[int]]:
1003
+ """
1004
+ Function to create a single convolutional layer.
1005
+
1006
+ Args:
1007
+ layer_index (int): The index of the current layer.
1008
+ reps (int): Number of repetitions for this layer.
1009
+ current_indices (List[int]): Indices of qubits for the current layer.
1010
+ params (dict): Dictionary to store and retrieve parameters.
1011
+ operations (List[Any]): List of quantum operations to apply in the gates.
1012
+ entangler (Any): Entangling operation, such as CZ.
1013
+ n_qubits (int): Total number of qubits.
1014
+
1015
+ Returns:
1016
+ Tuple[AbstractBlock, List[int]]: A tuple containing the quantum block
1017
+ for the layer and the target indices for the next layer.
1018
+ """
1019
+ current_layer = []
1020
+ next_indices = []
1021
+ spacing = layer_index
1022
+
1023
+ if layer_index in [0, 1]: # Special behavior for first two layers
1024
+ layer_reps = []
1025
+ for rep in range(max_reps):
1026
+ rep_kron = []
1027
+ # Define qubit pairs based on odd/even repetition
1028
+ if rep % 2 == 0: # Even d: regular behavior
1029
+ pairs = zip(current_indices[::2], current_indices[1::2])
1030
+ else: # Odd d: shift downward, leaving qubits 0 and 7 free
1031
+ pairs = zip(current_indices[1:-1:2], current_indices[2:-1:2])
1032
+
1033
+ # Build the gate sequence for each pair
1034
+ for control, target in pairs:
1035
+ W_pairs = _create_single_W(
1036
+ params,
1037
+ operations,
1038
+ entangler,
1039
+ layer_index,
1040
+ rep,
1041
+ max_reps,
1042
+ control,
1043
+ target,
1044
+ spacing,
1045
+ n_qubits,
1046
+ is_corr,
1047
+ )
1048
+ tag(W_pairs, f"W{control,target}")
1049
+ rep_kron.append(W_pairs)
1050
+
1051
+ layer_reps.append(kron(*rep_kron))
1052
+
1053
+ # Combine all repetitions using `chain`
1054
+ current_layer.append(chain(*layer_reps))
1055
+
1056
+ else: # Original behavior for other layers
1057
+ for rep in range(max_reps):
1058
+ for control, target in zip(current_indices[::2], current_indices[1::2]):
1059
+ W_pairs = _create_single_W(
1060
+ params,
1061
+ operations,
1062
+ entangler,
1063
+ layer_index,
1064
+ rep,
1065
+ max_reps,
1066
+ control,
1067
+ target,
1068
+ spacing,
1069
+ n_qubits,
1070
+ is_corr,
1071
+ )
1072
+ current_layer.append(W_pairs)
1073
+
1074
+ # Update `next_indices` with the **targets** of the current layer
1075
+ next_indices = current_indices[1::2]
1076
+ return chain(*current_layer), next_indices
@@ -0,0 +1,158 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Callable
4
+ from qadence.blocks import chain
5
+ from qadence.parameters import Parameter
6
+ from qadence.blocks.utils import add, tag
7
+ from qadence.operations import Z, RX, CZ
8
+ from qadence.circuit import QuantumCircuit
9
+ from qadence.types import BackendName, DiffMode
10
+ from qadence.blocks.abstract import AbstractBlock
11
+
12
+ from .models import QNN
13
+ from qadence.ml_tools.constructors import _create_conv_layer, _create_feature_map_qcnn
14
+
15
+
16
+ class QCNN(QNN):
17
+ def __init__(
18
+ self,
19
+ n_inputs: int,
20
+ n_qubits: int,
21
+ depth: list[int],
22
+ operations: list[Any],
23
+ entangler: Any = CZ,
24
+ random_meas: bool = True,
25
+ fm_basis: str = "Fourier",
26
+ fm_gate: Any = RX,
27
+ is_corr: bool = False,
28
+ **kwargs: Any,
29
+ ) -> None:
30
+ """
31
+ Creates a QCNN model.
32
+
33
+ Args:
34
+ n_inputs (int): Number of input features.
35
+ n_qubits (int): Total number of qubits.
36
+ depth (list[int]): List defining the depth (repetitions) of each layer.
37
+ operations (list[Any]): List of quantum operations to apply
38
+ in the gates (e.g., [RX, RZ]).
39
+ entangler (Any): Entangling operation, such as CZ.
40
+ random_meas (bool): If True, applies random weighted measurements.
41
+ fm_basis (str): feature map basis.
42
+ fm_gate (Any): gate employed in the fm, such as.
43
+ **kwargs (Any): Additional keyword arguments for the parent QNN class.
44
+ """
45
+ self.n_inputs = n_inputs
46
+ self.n_qubits = n_qubits
47
+ self.depth = depth
48
+ self.operations = operations
49
+ self.entangler = entangler
50
+ self.random_meas = random_meas
51
+ self.fm_basis = fm_basis
52
+ self.fm_gate = fm_gate
53
+ self.is_corr = is_corr
54
+
55
+ circuit = self.qcnn_circuit(
56
+ self.n_inputs,
57
+ self.n_qubits,
58
+ self.depth,
59
+ self.operations,
60
+ self.entangler,
61
+ self.fm_basis,
62
+ self.fm_gate,
63
+ self.is_corr,
64
+ )
65
+
66
+ obs = self.qcnn_deferred_obs(self.n_qubits, self.random_meas)
67
+
68
+ super().__init__(
69
+ circuit=circuit,
70
+ observable=obs,
71
+ backend=BackendName.PYQTORCH,
72
+ diff_mode=DiffMode.AD,
73
+ inputs=[f"\u03C6_{i}" for i in range(self.n_inputs)],
74
+ **kwargs,
75
+ )
76
+
77
+ def qcnn_circuit(
78
+ self,
79
+ n_inputs: int,
80
+ n_qubits: int,
81
+ depth: list[int],
82
+ operations: list[Any],
83
+ entangler: AbstractBlock,
84
+ fm_basis: str,
85
+ fm_gate: AbstractBlock,
86
+ is_corr: bool,
87
+ ) -> QuantumCircuit:
88
+ """Defines the QCNN circuit."""
89
+ # Validate qubit count
90
+ if n_qubits < 4:
91
+ raise ValueError(
92
+ f"Invalid number of qubits: {n_qubits}. " "At least 4 qubits are required."
93
+ )
94
+ if n_qubits % 2 != 0:
95
+ raise ValueError(
96
+ f"Invalid number of qubits: {n_qubits}. " "The number of qubits must be even."
97
+ )
98
+
99
+ # Validate that all values in `depth` are odd
100
+ even_depths = [d for d in depth if d % 2 == 0]
101
+ if even_depths:
102
+ raise ValueError(
103
+ f"Invalid depth values: '{even_depths[0]}'. " "All the conv layer 'r's must be odd."
104
+ )
105
+
106
+ # Feature map (FM)
107
+ fm = _create_feature_map_qcnn(n_qubits, n_inputs, fm_basis, fm_gate)
108
+ tag(fm, "FM")
109
+
110
+ # Conv and Pool layer definition
111
+ conv_layers = []
112
+ params: dict[str, Parameter] = {}
113
+
114
+ # Define layer all the 2-qubit patterns based on depth
115
+ layer_patterns = [(2**layer_index, depth[layer_index]) for layer_index in range(len(depth))]
116
+
117
+ # Initialize all qubits for the current layer
118
+ current_indices = list(range(n_qubits))
119
+
120
+ # Build the circuit layer by layer using the helper
121
+ for layer_index, (_, reps) in enumerate(layer_patterns):
122
+ if reps == 0:
123
+ raise ValueError(f"Invalid layer {layer_index}: zero repetitions (reps = {reps}).")
124
+ if len(current_indices) < 2:
125
+ raise RuntimeError(
126
+ f"Layer {layer_index} requires at least 2 qubits, "
127
+ f"but found {len(current_indices)}."
128
+ )
129
+
130
+ layer_block, next_indices = _create_conv_layer(
131
+ layer_index, reps, current_indices, params, operations, entangler, n_qubits, is_corr
132
+ )
133
+ tag(layer_block, f"C+P layer {layer_index}")
134
+ conv_layers.append(layer_block)
135
+
136
+ # Update `current_indices` for the next layer
137
+ current_indices = next_indices
138
+
139
+ # Combine all layers for the final ansatz
140
+ ansatz = chain(*conv_layers)
141
+
142
+ return QuantumCircuit(n_qubits, fm, ansatz)
143
+
144
+ def qcnn_deferred_obs(
145
+ self, n_qubits: int, random_meas: bool
146
+ ) -> AbstractBlock | list[AbstractBlock]:
147
+ """
148
+ Defines the measurements to be performedthe traced out.
149
+
150
+ and remaining qubits.
151
+ """
152
+ if random_meas:
153
+ w1 = [Parameter(f"w{i}") for i in range(n_qubits)]
154
+ obs = add(Z(i) * w for i, w in zip(range(n_qubits), w1))
155
+ else:
156
+ obs = add(Z(i) for i in range(n_qubits))
157
+
158
+ return obs
qadence/model.py CHANGED
@@ -154,6 +154,11 @@ class QuantumModel(nn.Module):
154
154
  """Variational parameters."""
155
155
  return OrderedDict({k: v.data for k, v in self._params.items() if v.requires_grad})
156
156
 
157
+ @property
158
+ def params(self) -> OrderedDict:
159
+ """All parameters."""
160
+ return OrderedDict({k: v.data for k, v in self._params.items()})
161
+
157
162
  @property
158
163
  def vals_vparams(self) -> Tensor:
159
164
  """Dictionary with parameters which are actually updated during optimization."""
@@ -176,6 +181,19 @@ class QuantumModel(nn.Module):
176
181
  """The number of variational parameters."""
177
182
  return len(self.vals_vparams)
178
183
 
184
+ @property
185
+ def show_config(self) -> str:
186
+ """Attain current quantum model configurations."""
187
+ if isinstance(self.backend, DifferentiableBackend):
188
+ current_config = self.backend.backend.config
189
+ return BackendConfiguration.available_options(current_config)
190
+
191
+ def change_config(self, new_config: dict) -> None:
192
+ """Change configuration with the input."""
193
+ if isinstance(self.backend, DifferentiableBackend):
194
+ current_config = self.backend.backend.config
195
+ BackendConfiguration.change_config(current_config, new_config)
196
+
179
197
  def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
180
198
  """Get backend-converted circuit.
181
199
 
@@ -520,7 +538,7 @@ class QuantumModel(nn.Module):
520
538
  file_path = file_path / get_latest_checkpoint_name(file_path, "model")
521
539
 
522
540
  try:
523
- qm_pt = torch.load(file_path, map_location=map_location)
541
+ qm_pt = torch.load(file_path, map_location=map_location, weights_only=False)
524
542
  except Exception as e:
525
543
  logger.error(f"Unable to load QuantumModel due to {e}")
526
544
  return cls._from_dict(qm_pt, as_torch)
qadence/parameters.py CHANGED
@@ -225,6 +225,8 @@ def sympy_to_numeric(expr: Basic) -> TNumber:
225
225
  if expr.as_real_imag()[1] != 0:
226
226
  return complex(expr)
227
227
  else:
228
+ if expr.is_Integer:
229
+ return int(expr)
228
230
  return float(expr)
229
231
 
230
232
 
qadence/serialization.py CHANGED
@@ -226,7 +226,7 @@ def save_json(d: dict, file_path: str | Path) -> None:
226
226
 
227
227
 
228
228
  def load_pt(file_path: str | Path, map_location: str) -> Any:
229
- return torch.load(file_path, map_location=map_location)
229
+ return torch.load(file_path, map_location=map_location, weights_only=False)
230
230
 
231
231
 
232
232
  def load_json(file_path: str | Path, map_location: str) -> Any:
qadence/types.py CHANGED
@@ -180,7 +180,7 @@ class AnsatzType(StrEnum):
180
180
  """Alternating Layer Ansatz."""
181
181
 
182
182
 
183
- class _DiffMode(StrEnum):
183
+ class DiffMode(StrEnum):
184
184
  """Differentiation modes to choose from."""
185
185
 
186
186
  GPSR = "gpsr"
@@ -246,11 +246,9 @@ class _Engine(StrEnum):
246
246
  try:
247
247
  module = importlib.import_module("qadence_extensions.types")
248
248
  BackendName = getattr(module, "BackendName")
249
- DiffMode = getattr(module, "DiffMode")
250
249
  Engine = getattr(module, "Engine")
251
250
  except ModuleNotFoundError:
252
251
  BackendName = _BackendName
253
- DiffMode = _DiffMode
254
252
  Engine = _Engine
255
253
 
256
254
 
qadence/utils.py CHANGED
@@ -318,14 +318,23 @@ def block_to_mathematical_expression(block: Tree | AbstractBlock) -> str:
318
318
  [block_to_mathematical_expression(block_child) for block_child in block_tree.children]
319
319
  )
320
320
  if "mul" in block_title:
321
- block_title = re.findall("\d+\.\d+", block_title)[0]
322
- coeff = float(block_title)
323
- if coeff == 0:
324
- block_title = ""
325
- elif coeff == 1:
326
- block_title = block_to_mathematical_expression(block_tree.children[0])
327
- else:
321
+ block_title = re.findall("\[mul:\s*(.+?)\]", block_title)[0]
322
+
323
+ try:
324
+ if "." in block_title:
325
+ coeff = float(block_title)
326
+ else:
327
+ coeff = int(block_title)
328
+ if coeff == 0:
329
+ block_title = ""
330
+ elif coeff == 1:
331
+ block_title = block_to_mathematical_expression(block_tree.children[0])
332
+ else:
333
+ block_title += " * " + block_to_mathematical_expression(block_tree.children[0])
334
+
335
+ except ValueError: # In case block_title is a non-numeric str (e.g. parameter name)
328
336
  block_title += " * " + block_to_mathematical_expression(block_tree.children[0])
337
+
329
338
  first_part = block_title[:3]
330
339
  if first_part in [" + ", " ⊗ ", " * "]:
331
340
  block_title = block_title[3:]
@@ -1,17 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qadence
3
- Version: 1.11.1
3
+ Version: 1.11.2
4
4
  Summary: Pasqal interface for circuit-based quantum computing SDKs
5
5
  Author-email: Aleksander Wennersteen <aleksander.wennersteen@pasqal.com>, Gert-Jan Both <gert-jan.both@pasqal.com>, Niklas Heim <niklas.heim@pasqal.com>, Mario Dagrada <mario.dagrada@pasqal.com>, Vincent Elfving <vincent.elfving@pasqal.com>, Dominik Seitz <dominik.seitz@pasqal.com>, Roland Guichard <roland.guichard@pasqal.com>, "Joao P. Moutinho" <joao.moutinho@pasqal.com>, Vytautas Abramavicius <vytautas.abramavicius@pasqal.com>, Gergana Velikova <gergana.velikova@pasqal.com>, Eduardo Maschio <eduardo.maschio@pasqal.com>, Smit Chaudhary <smit.chaudhary@pasqal.com>, Ignacio Fernández Graña <ignacio.fernandez-grana@pasqal.com>, Charles Moussa <charles.moussa@pasqal.com>, Giorgio Tosti Balducci <giorgio.tosti-balducci@pasqal.com>, Daniele Cucurachi <daniele.cucurachi@pasqal.com>, Pim Venderbosch <pim.venderbosch@pasqal.com>, Manu Lahariya <manu.lahariya@pasqal.com>
6
- License: Apache 2.0
6
+ License: PASQAL OPEN-SOURCE SOFTWARE LICENSE (MIT-derived)
7
7
  License-File: LICENSE
8
- Classifier: License :: OSI Approved :: Apache Software License
8
+ Classifier: License :: Other/Proprietary License
9
9
  Classifier: Programming Language :: Python
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.9
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
15
16
  Classifier: Programming Language :: Python :: Implementation :: CPython
16
17
  Classifier: Programming Language :: Python :: Implementation :: PyPy
17
18
  Requires-Python: >=3.9
@@ -23,11 +24,11 @@ Requires-Dist: nevergrad
23
24
  Requires-Dist: numpy
24
25
  Requires-Dist: openfermion
25
26
  Requires-Dist: pasqal-cloud
26
- Requires-Dist: pyqtorch==1.7.2
27
+ Requires-Dist: pyqtorch==1.7.5
27
28
  Requires-Dist: pyyaml
28
29
  Requires-Dist: rich
29
30
  Requires-Dist: scipy
30
- Requires-Dist: sympy<1.13
31
+ Requires-Dist: sympy<1.13.4
31
32
  Requires-Dist: sympytorch>=0.1.2
32
33
  Requires-Dist: tensorboard>=2.12.0
33
34
  Requires-Dist: torch
@@ -43,7 +44,7 @@ Requires-Dist: nvidia-pyindex; extra == 'dlprof'
43
44
  Provides-Extra: horqrux
44
45
  Requires-Dist: einops; extra == 'horqrux'
45
46
  Requires-Dist: flax; extra == 'horqrux'
46
- Requires-Dist: horqrux==0.7.0; extra == 'horqrux'
47
+ Requires-Dist: horqrux==0.8.0; extra == 'horqrux'
47
48
  Requires-Dist: jax; extra == 'horqrux'
48
49
  Requires-Dist: jaxopt; extra == 'horqrux'
49
50
  Requires-Dist: optax; extra == 'horqrux'
@@ -56,8 +57,8 @@ Provides-Extra: protocols
56
57
  Requires-Dist: qadence-protocols; extra == 'protocols'
57
58
  Provides-Extra: pulser
58
59
  Requires-Dist: pasqal-cloud==0.20.2; extra == 'pulser'
59
- Requires-Dist: pulser-core==1.3.0; extra == 'pulser'
60
- Requires-Dist: pulser-simulation==1.3.0; extra == 'pulser'
60
+ Requires-Dist: pulser-core==1.4.0; extra == 'pulser'
61
+ Requires-Dist: pulser-simulation==1.4.0; extra == 'pulser'
61
62
  Provides-Extra: visualization
62
63
  Requires-Dist: graphviz; extra == 'visualization'
63
64
  Description-Content-Type: text/markdown
@@ -84,7 +85,7 @@ programs** with tunable qubit interactions and arbitrary register topologies rea
84
85
  [![Tests](https://github.com/pasqal-io/qadence/actions/workflows/test_fast.yml/badge.svg)](https://github.com/pasqal-io/qadence/actions/workflows/test_fast.yml)
85
86
  [![Documentation](https://github.com/pasqal-io/qadence/actions/workflows/build_docs.yml/badge.svg)](https://pasqal-io.github.io/qadence/latest)
86
87
  [![Pypi](https://badge.fury.io/py/qadence.svg)](https://pypi.org/project/qadence/)
87
- [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
88
+ [![License](https://img.shields.io/badge/License-MIT--derived-yellow.svg)](https://opensource.org/licenses/MIT)
88
89
  ![Coverage](https://img.shields.io/codecov/c/github/pasqal-io/qadence?style=flat-square)
89
90
 
90
91
 
@@ -215,4 +216,4 @@ doi = {10.1109/MS.2025.3536607}
215
216
  ```
216
217
 
217
218
  ## License
218
- Qadence is a free and open source software package, released under the Apache License, Version 2.0.
219
+ Qadence is a free and open source software package, released under the PASQAL OPEN-SOURCE SOFTWARE LICENSE (MIT-derived).