qadence 1.9.1__py3-none-any.whl → 1.10.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.
- qadence/analog/device.py +7 -0
- qadence/backends/api.py +3 -3
- qadence/backends/horqrux/convert_ops.py +3 -1
- qadence/backends/pulser/backend.py +1 -1
- qadence/backends/pyqtorch/convert_ops.py +5 -5
- qadence/backends/utils.py +15 -1
- qadence/blocks/embedding.py +7 -6
- qadence/blocks/utils.py +5 -3
- qadence/constructors/__init__.py +5 -4
- qadence/constructors/ala.py +270 -0
- qadence/constructors/{ansatze.py → hea.py} +76 -195
- qadence/constructors/iia.py +31 -0
- qadence/engines/torch/differentiable_expectation.py +3 -1
- qadence/extensions.py +4 -8
- qadence/measurements/shadow.py +30 -10
- qadence/ml_tools/callbacks/__init__.py +10 -0
- qadence/ml_tools/callbacks/callback.py +325 -1
- qadence/ml_tools/callbacks/writer_registry.py +17 -17
- qadence/ml_tools/constructors.py +8 -6
- qadence/ml_tools/trainer.py +28 -23
- qadence/operations/control_ops.py +3 -9
- qadence/pasqal_cloud_connection.py +235 -0
- qadence/states.py +21 -0
- qadence/transpile/digitalize.py +4 -4
- qadence/transpile/flatten.py +4 -4
- qadence/transpile/invert.py +6 -12
- qadence/transpile/transpile.py +2 -4
- qadence/types.py +1 -1
- {qadence-1.9.1.dist-info → qadence-1.10.0.dist-info}/METADATA +9 -6
- {qadence-1.9.1.dist-info → qadence-1.10.0.dist-info}/RECORD +32 -30
- {qadence-1.9.1.dist-info → qadence-1.10.0.dist-info}/WHEEL +1 -1
- {qadence-1.9.1.dist-info → qadence-1.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import math
|
4
|
+
from logging import getLogger
|
3
5
|
from typing import Any, Callable
|
4
6
|
|
5
7
|
from qadence.ml_tools.callbacks.saveload import load_checkpoint, write_checkpoint
|
@@ -12,6 +14,8 @@ from qadence.ml_tools.stages import TrainingStage
|
|
12
14
|
CallbackFunction = Callable[..., Any]
|
13
15
|
CallbackConditionFunction = Callable[..., bool]
|
14
16
|
|
17
|
+
logger = getLogger("ml_tools")
|
18
|
+
|
15
19
|
|
16
20
|
class Callback:
|
17
21
|
"""Base class for defining various training callbacks.
|
@@ -258,7 +262,7 @@ class WriteMetrics(Callback):
|
|
258
262
|
writer (BaseWriter ): The writer object for logging.
|
259
263
|
"""
|
260
264
|
opt_result = trainer.opt_result
|
261
|
-
writer.write(opt_result)
|
265
|
+
writer.write(opt_result.iteration, opt_result.metrics)
|
262
266
|
|
263
267
|
|
264
268
|
class PlotMetrics(Callback):
|
@@ -449,3 +453,323 @@ class LogModelTracker(Callback):
|
|
449
453
|
writer.log_model(
|
450
454
|
model, trainer.train_dataloader, trainer.val_dataloader, trainer.test_dataloader
|
451
455
|
)
|
456
|
+
|
457
|
+
|
458
|
+
class LRSchedulerStepDecay(Callback):
|
459
|
+
"""
|
460
|
+
Reduces the learning rate by a factor at regular intervals.
|
461
|
+
|
462
|
+
This callback adjusts the learning rate by multiplying it with a decay factor
|
463
|
+
after a specified number of iterations. The learning rate is updated as:
|
464
|
+
lr = lr * gamma
|
465
|
+
|
466
|
+
Example Usage in `TrainConfig`:
|
467
|
+
To use `LRSchedulerStepDecay`, include it in the `callbacks` list when setting
|
468
|
+
up your `TrainConfig`:
|
469
|
+
```python exec="on" source="material-block" result="json"
|
470
|
+
from qadence.ml_tools import TrainConfig
|
471
|
+
from qadence.ml_tools.callbacks import LRSchedulerStepDecay
|
472
|
+
|
473
|
+
# Create an instance of the LRSchedulerStepDecay callback
|
474
|
+
lr_step_decay = LRSchedulerStepDecay(on="train_epoch_end",
|
475
|
+
called_every=100,
|
476
|
+
gamma=0.5)
|
477
|
+
|
478
|
+
config = TrainConfig(
|
479
|
+
max_iter=10000,
|
480
|
+
# Print metrics every 1000 training epochs
|
481
|
+
print_every=1000,
|
482
|
+
# Add the custom callback
|
483
|
+
callbacks=[lr_step_decay]
|
484
|
+
)
|
485
|
+
```
|
486
|
+
"""
|
487
|
+
|
488
|
+
def __init__(self, on: str, called_every: int, gamma: float = 0.5):
|
489
|
+
"""Initializes the LRSchedulerStepDecay callback.
|
490
|
+
|
491
|
+
Args:
|
492
|
+
on (str): The event to trigger the callback.
|
493
|
+
called_every (int): Frequency of callback calls in terms of iterations.
|
494
|
+
gamma (float, optional): The decay factor applied to the learning rate.
|
495
|
+
A value < 1 reduces the learning rate over time. Default is 0.5.
|
496
|
+
"""
|
497
|
+
super().__init__(on=on, called_every=called_every)
|
498
|
+
self.gamma = gamma
|
499
|
+
|
500
|
+
def run_callback(self, trainer: Any, config: TrainConfig, writer: BaseWriter) -> None:
|
501
|
+
"""
|
502
|
+
Runs the callback to apply step decay to the learning rate.
|
503
|
+
|
504
|
+
Args:
|
505
|
+
trainer (Any): The training object.
|
506
|
+
config (TrainConfig): The configuration object.
|
507
|
+
writer (BaseWriter): The writer object for logging.
|
508
|
+
"""
|
509
|
+
for param_group in trainer.optimizer.param_groups:
|
510
|
+
param_group["lr"] *= self.gamma
|
511
|
+
|
512
|
+
|
513
|
+
class LRSchedulerCyclic(Callback):
|
514
|
+
"""
|
515
|
+
Applies a cyclic learning rate schedule during training.
|
516
|
+
|
517
|
+
This callback oscillates the learning rate between a minimum (base_lr)
|
518
|
+
and a maximum (max_lr) over a defined cycle length (step_size). The learning
|
519
|
+
rate follows a triangular wave pattern.
|
520
|
+
|
521
|
+
Example Usage in `TrainConfig`:
|
522
|
+
To use `LRSchedulerCyclic`, include it in the `callbacks` list when setting
|
523
|
+
up your `TrainConfig`:
|
524
|
+
```python exec="on" source="material-block" result="json"
|
525
|
+
from qadence.ml_tools import TrainConfig
|
526
|
+
from qadence.ml_tools.callbacks import LRSchedulerCyclic
|
527
|
+
|
528
|
+
# Create an instance of the LRSchedulerCyclic callback
|
529
|
+
lr_cyclic = LRSchedulerCyclic(on="train_batch_end",
|
530
|
+
called_every=1,
|
531
|
+
base_lr=0.001,
|
532
|
+
max_lr=0.01,
|
533
|
+
step_size=2000)
|
534
|
+
|
535
|
+
config = TrainConfig(
|
536
|
+
max_iter=10000,
|
537
|
+
# Print metrics every 1000 training epochs
|
538
|
+
print_every=1000,
|
539
|
+
# Add the custom callback
|
540
|
+
callbacks=[lr_cyclic]
|
541
|
+
)
|
542
|
+
```
|
543
|
+
"""
|
544
|
+
|
545
|
+
def __init__(self, on: str, called_every: int, base_lr: float, max_lr: float, step_size: int):
|
546
|
+
"""Initializes the LRSchedulerCyclic callback.
|
547
|
+
|
548
|
+
Args:
|
549
|
+
on (str): The event to trigger the callback.
|
550
|
+
called_every (int): Frequency of callback calls in terms of iterations.
|
551
|
+
base_lr (float): The minimum learning rate.
|
552
|
+
max_lr (float): The maximum learning rate.
|
553
|
+
step_size (int): Number of iterations for half a cycle.
|
554
|
+
"""
|
555
|
+
super().__init__(on=on, called_every=called_every)
|
556
|
+
self.base_lr = base_lr
|
557
|
+
self.max_lr = max_lr
|
558
|
+
self.step_size = step_size
|
559
|
+
|
560
|
+
def run_callback(self, trainer: Any, config: TrainConfig, writer: BaseWriter) -> None:
|
561
|
+
"""
|
562
|
+
Adjusts the learning rate cyclically.
|
563
|
+
|
564
|
+
Args:
|
565
|
+
trainer (Any): The training object.
|
566
|
+
config (TrainConfig): The configuration object.
|
567
|
+
writer (BaseWriter): The writer object for logging.
|
568
|
+
"""
|
569
|
+
cycle = trainer.opt_result.iteration // (2 * self.step_size)
|
570
|
+
x = abs(trainer.opt_result.iteration / self.step_size - 2 * cycle - 1)
|
571
|
+
scale = max(0, (1 - x))
|
572
|
+
new_lr = self.base_lr + (self.max_lr - self.base_lr) * scale
|
573
|
+
for param_group in trainer.optimizer.param_groups:
|
574
|
+
param_group["lr"] = new_lr
|
575
|
+
|
576
|
+
|
577
|
+
class LRSchedulerCosineAnnealing(Callback):
|
578
|
+
"""
|
579
|
+
Applies cosine annealing to the learning rate during training.
|
580
|
+
|
581
|
+
This callback decreases the learning rate following a cosine curve,
|
582
|
+
starting from the initial learning rate and annealing to a minimum (min_lr).
|
583
|
+
|
584
|
+
Example Usage in `TrainConfig`:
|
585
|
+
To use `LRSchedulerCosineAnnealing`, include it in the `callbacks` list
|
586
|
+
when setting up your `TrainConfig`:
|
587
|
+
```python exec="on" source="material-block" result="json"
|
588
|
+
from qadence.ml_tools import TrainConfig
|
589
|
+
from qadence.ml_tools.callbacks import LRSchedulerCosineAnnealing
|
590
|
+
|
591
|
+
# Create an instance of the LRSchedulerCosineAnnealing callback
|
592
|
+
lr_cosine = LRSchedulerCosineAnnealing(on="train_batch_end",
|
593
|
+
called_every=1,
|
594
|
+
t_max=5000,
|
595
|
+
min_lr=1e-6)
|
596
|
+
|
597
|
+
config = TrainConfig(
|
598
|
+
max_iter=10000,
|
599
|
+
# Print metrics every 1000 training epochs
|
600
|
+
print_every=1000,
|
601
|
+
# Add the custom callback
|
602
|
+
callbacks=[lr_cosine]
|
603
|
+
)
|
604
|
+
```
|
605
|
+
"""
|
606
|
+
|
607
|
+
def __init__(self, on: str, called_every: int, t_max: int, min_lr: float = 0.0):
|
608
|
+
"""Initializes the LRSchedulerCosineAnnealing callback.
|
609
|
+
|
610
|
+
Args:
|
611
|
+
on (str): The event to trigger the callback.
|
612
|
+
called_every (int): Frequency of callback calls in terms of iterations.
|
613
|
+
t_max (int): The total number of iterations for one annealing cycle.
|
614
|
+
min_lr (float, optional): The minimum learning rate. Default is 0.0.
|
615
|
+
"""
|
616
|
+
super().__init__(on=on, called_every=called_every)
|
617
|
+
self.t_max = t_max
|
618
|
+
self.min_lr = min_lr
|
619
|
+
|
620
|
+
def run_callback(self, trainer: Any, config: TrainConfig, writer: BaseWriter) -> None:
|
621
|
+
"""
|
622
|
+
Adjusts the learning rate using cosine annealing.
|
623
|
+
|
624
|
+
Args:
|
625
|
+
trainer (Any): The training object.
|
626
|
+
config (TrainConfig): The configuration object.
|
627
|
+
writer (BaseWriter): The writer object for logging.
|
628
|
+
"""
|
629
|
+
for param_group in trainer.optimizer.param_groups:
|
630
|
+
max_lr = param_group["lr"]
|
631
|
+
new_lr = (
|
632
|
+
self.min_lr
|
633
|
+
+ (max_lr - self.min_lr)
|
634
|
+
* (1 + math.cos(math.pi * trainer.opt_result.iteration / self.t_max))
|
635
|
+
/ 2
|
636
|
+
)
|
637
|
+
param_group["lr"] = new_lr
|
638
|
+
|
639
|
+
|
640
|
+
class EarlyStopping(Callback):
|
641
|
+
"""
|
642
|
+
Stops training when a monitored metric has not improved for a specified number of epochs.
|
643
|
+
|
644
|
+
This callback monitors a specified metric (e.g., validation loss or accuracy). If the metric
|
645
|
+
does not improve for a given patience period, training is stopped.
|
646
|
+
|
647
|
+
Example Usage in `TrainConfig`:
|
648
|
+
To use `EarlyStopping`, include it in the `callbacks` list when setting up your `TrainConfig`:
|
649
|
+
```python exec="on" source="material-block" result="json"
|
650
|
+
from qadence.ml_tools import TrainConfig
|
651
|
+
from qadence.ml_tools.callbacks import EarlyStopping
|
652
|
+
|
653
|
+
# Create an instance of the EarlyStopping callback
|
654
|
+
early_stopping = EarlyStopping(on="val_epoch_end",
|
655
|
+
called_every=1,
|
656
|
+
monitor="val_loss",
|
657
|
+
patience=5,
|
658
|
+
mode="min")
|
659
|
+
|
660
|
+
config = TrainConfig(
|
661
|
+
max_iter=10000,
|
662
|
+
print_every=1000,
|
663
|
+
callbacks=[early_stopping]
|
664
|
+
)
|
665
|
+
```
|
666
|
+
"""
|
667
|
+
|
668
|
+
def __init__(
|
669
|
+
self, on: str, called_every: int, monitor: str, patience: int = 5, mode: str = "min"
|
670
|
+
):
|
671
|
+
"""Initializes the EarlyStopping callback.
|
672
|
+
|
673
|
+
Args:
|
674
|
+
on (str): The event to trigger the callback (e.g., "val_epoch_end").
|
675
|
+
called_every (int): Frequency of callback calls in terms of iterations.
|
676
|
+
monitor (str): The metric to monitor (e.g., "val_loss" or "train_loss").
|
677
|
+
All metrics returned by optimize step are available to monitor.
|
678
|
+
Please add "val_" and "train_" strings at the start of the metric name.
|
679
|
+
patience (int, optional): Number of iterations to wait for improvement. Default is 5.
|
680
|
+
mode (str, optional): Whether to minimize ("min") or maximize ("max") the metric.
|
681
|
+
Default is "min".
|
682
|
+
"""
|
683
|
+
super().__init__(on=on, called_every=called_every)
|
684
|
+
self.monitor = monitor
|
685
|
+
self.patience = patience
|
686
|
+
self.mode = mode
|
687
|
+
self.best_value = float("inf") if mode == "min" else -float("inf")
|
688
|
+
self.counter = 0
|
689
|
+
|
690
|
+
def run_callback(self, trainer: Any, config: TrainConfig, writer: BaseWriter) -> None:
|
691
|
+
"""
|
692
|
+
Monitors the metric and stops training if no improvement is observed.
|
693
|
+
|
694
|
+
Args:
|
695
|
+
trainer (Any): The training object.
|
696
|
+
config (TrainConfig): The configuration object.
|
697
|
+
writer (BaseWriter): The writer object for logging.
|
698
|
+
"""
|
699
|
+
current_value = trainer.opt_result.metrics.get(self.monitor)
|
700
|
+
if current_value is None:
|
701
|
+
raise ValueError(f"Metric '{self.monitor}' is not available in the trainer's metrics.")
|
702
|
+
|
703
|
+
if (self.mode == "min" and current_value < self.best_value) or (
|
704
|
+
self.mode == "max" and current_value > self.best_value
|
705
|
+
):
|
706
|
+
self.best_value = current_value
|
707
|
+
self.counter = 0
|
708
|
+
else:
|
709
|
+
self.counter += 1
|
710
|
+
|
711
|
+
if self.counter >= self.patience:
|
712
|
+
logger.info(
|
713
|
+
f"EarlyStopping: No improvement in '{self.monitor}' for {self.patience} epochs. "
|
714
|
+
"Stopping training."
|
715
|
+
)
|
716
|
+
trainer.stop_training = True
|
717
|
+
|
718
|
+
|
719
|
+
class GradientMonitoring(Callback):
|
720
|
+
"""
|
721
|
+
Logs gradient statistics (e.g., mean, standard deviation, max) during training.
|
722
|
+
|
723
|
+
This callback monitors and logs statistics about the gradients of the model parameters
|
724
|
+
to help debug or optimize the training process.
|
725
|
+
|
726
|
+
Example Usage in `TrainConfig`:
|
727
|
+
To use `GradientMonitoring`, include it in the `callbacks` list when
|
728
|
+
setting up your `TrainConfig`:
|
729
|
+
```python exec="on" source="material-block" result="json"
|
730
|
+
from qadence.ml_tools import TrainConfig
|
731
|
+
from qadence.ml_tools.callbacks import GradientMonitoring
|
732
|
+
|
733
|
+
# Create an instance of the GradientMonitoring callback
|
734
|
+
gradient_monitoring = GradientMonitoring(on="train_batch_end", called_every=10)
|
735
|
+
|
736
|
+
config = TrainConfig(
|
737
|
+
max_iter=10000,
|
738
|
+
print_every=1000,
|
739
|
+
callbacks=[gradient_monitoring]
|
740
|
+
)
|
741
|
+
```
|
742
|
+
"""
|
743
|
+
|
744
|
+
def __init__(self, on: str, called_every: int = 1):
|
745
|
+
"""Initializes the GradientMonitoring callback.
|
746
|
+
|
747
|
+
Args:
|
748
|
+
on (str): The event to trigger the callback (e.g., "train_batch_end").
|
749
|
+
called_every (int): Frequency of callback calls in terms of iterations.
|
750
|
+
"""
|
751
|
+
super().__init__(on=on, called_every=called_every)
|
752
|
+
|
753
|
+
def run_callback(self, trainer: Any, config: TrainConfig, writer: BaseWriter) -> None:
|
754
|
+
"""
|
755
|
+
Logs gradient statistics.
|
756
|
+
|
757
|
+
Args:
|
758
|
+
trainer (Any): The training object.
|
759
|
+
config (TrainConfig): The configuration object.
|
760
|
+
writer (BaseWriter): The writer object for logging.
|
761
|
+
"""
|
762
|
+
gradient_stats = {}
|
763
|
+
for name, param in trainer.model.named_parameters():
|
764
|
+
if param.grad is not None:
|
765
|
+
grad = param.grad
|
766
|
+
gradient_stats.update(
|
767
|
+
{
|
768
|
+
name + "_mean": grad.mean().item(),
|
769
|
+
name + "_std": grad.std().item(),
|
770
|
+
name + "_max": grad.max().item(),
|
771
|
+
name + "_min": grad.min().item(),
|
772
|
+
}
|
773
|
+
)
|
774
|
+
|
775
|
+
writer.write(trainer.opt_result.iteration, gradient_stats)
|
@@ -60,12 +60,14 @@ class BaseWriter(ABC):
|
|
60
60
|
raise NotImplementedError("Writers must implement a close method.")
|
61
61
|
|
62
62
|
@abstractmethod
|
63
|
-
def write(self,
|
63
|
+
def write(self, iteration: int, metrics: dict) -> None:
|
64
64
|
"""
|
65
65
|
Logs the results of the current iteration.
|
66
66
|
|
67
67
|
Args:
|
68
|
-
|
68
|
+
iteration (int): The current training iteration.
|
69
|
+
metrics (dict): A dictionary of metrics to log, where keys are metric names
|
70
|
+
and values are the corresponding metric values.
|
69
71
|
"""
|
70
72
|
raise NotImplementedError("Writers must implement a write method.")
|
71
73
|
|
@@ -166,23 +168,22 @@ class TensorBoardWriter(BaseWriter):
|
|
166
168
|
if self.writer:
|
167
169
|
self.writer.close()
|
168
170
|
|
169
|
-
def write(self,
|
171
|
+
def write(self, iteration: int, metrics: dict) -> None:
|
170
172
|
"""
|
171
173
|
Logs the results of the current iteration to TensorBoard.
|
172
174
|
|
173
175
|
Args:
|
174
|
-
|
176
|
+
iteration (int): The current training iteration.
|
177
|
+
metrics (dict): A dictionary of metrics to log, where keys are metric names
|
178
|
+
and values are the corresponding metric values.
|
175
179
|
"""
|
176
|
-
# Not writing loss as loss is available in the metrics
|
177
|
-
# if result.loss is not None:
|
178
|
-
# self.writer.add_scalar("loss", float(result.loss), result.iteration)
|
179
180
|
if self.writer:
|
180
|
-
for key, value in
|
181
|
-
self.writer.add_scalar(key, value,
|
181
|
+
for key, value in metrics.items():
|
182
|
+
self.writer.add_scalar(key, value, iteration)
|
182
183
|
else:
|
183
184
|
raise RuntimeError(
|
184
185
|
"The writer is not initialized."
|
185
|
-
"Please call the 'writer.open()' method before writing"
|
186
|
+
"Please call the 'writer.open()' method before writing."
|
186
187
|
)
|
187
188
|
|
188
189
|
def log_hyperparams(self, hyperparams: dict) -> None:
|
@@ -305,22 +306,21 @@ class MLFlowWriter(BaseWriter):
|
|
305
306
|
if self.run:
|
306
307
|
self.mlflow.end_run()
|
307
308
|
|
308
|
-
def write(self,
|
309
|
+
def write(self, iteration: int, metrics: dict) -> None:
|
309
310
|
"""
|
310
311
|
Logs the results of the current iteration to MLflow.
|
311
312
|
|
312
313
|
Args:
|
313
|
-
|
314
|
+
iteration (int): The current training iteration.
|
315
|
+
metrics (dict): A dictionary of metrics to log, where keys are metric names
|
316
|
+
and values are the corresponding metric values.
|
314
317
|
"""
|
315
|
-
# Not writing loss as loss is available in the metrics
|
316
|
-
# if result.loss is not None:
|
317
|
-
# self.mlflow.log_metric("loss", float(result.loss), step=result.iteration)
|
318
318
|
if self.mlflow:
|
319
|
-
self.mlflow.log_metrics(
|
319
|
+
self.mlflow.log_metrics(metrics, step=iteration)
|
320
320
|
else:
|
321
321
|
raise RuntimeError(
|
322
322
|
"The writer is not initialized."
|
323
|
-
"Please call the 'writer.open()' method before writing"
|
323
|
+
"Please call the 'writer.open()' method before writing."
|
324
324
|
)
|
325
325
|
|
326
326
|
def log_hyperparams(self, hyperparams: dict) -> None:
|
qadence/ml_tools/constructors.py
CHANGED
@@ -13,13 +13,13 @@ from qadence.constructors import (
|
|
13
13
|
analog_feature_map,
|
14
14
|
feature_map,
|
15
15
|
hamiltonian_factory,
|
16
|
-
|
16
|
+
iia,
|
17
17
|
rydberg_feature_map,
|
18
18
|
rydberg_hea,
|
19
19
|
rydberg_tower_feature_map,
|
20
20
|
)
|
21
|
-
from qadence.constructors.ansatze import hea_digital, hea_sDAQC
|
22
21
|
from qadence.constructors.hamiltonians import ObservableConfig, TDetuning
|
22
|
+
from qadence.constructors.hea import hea_digital, hea_sDAQC
|
23
23
|
from qadence.measurements import Measurements
|
24
24
|
from qadence.noise import NoiseHandler
|
25
25
|
from qadence.operations import CNOT, RX, RY, I, N, Z
|
@@ -107,7 +107,8 @@ def _encode_features_series_digital(
|
|
107
107
|
)
|
108
108
|
|
109
109
|
support_arrays = {
|
110
|
-
key: support
|
110
|
+
key: support
|
111
|
+
for key, support in zip(config.inputs, support_arrays_list) # type: ignore[union-attr, arg-type]
|
111
112
|
}
|
112
113
|
|
113
114
|
num_uploads = {key: value + 1 for key, value in config.num_repeats.items()} # type: ignore[union-attr]
|
@@ -163,7 +164,8 @@ def _encode_features_parallel_digital(
|
|
163
164
|
)
|
164
165
|
|
165
166
|
support_arrays = {
|
166
|
-
key: support
|
167
|
+
key: support
|
168
|
+
for key, support in zip(config.inputs, support_arrays_list) # type: ignore[union-attr, arg-type]
|
167
169
|
}
|
168
170
|
|
169
171
|
num_uploads = {key: value + 1 for key, value in config.num_repeats.items()} # type: ignore[union-attr]
|
@@ -412,7 +414,7 @@ def _create_iia_digital(
|
|
412
414
|
entangler = config.strategy_args.get("entangler", CNOT)
|
413
415
|
periodic = config.strategy_args.get("periodic", False)
|
414
416
|
|
415
|
-
return
|
417
|
+
return iia(
|
416
418
|
n_qubits=num_qubits,
|
417
419
|
depth=config.depth,
|
418
420
|
param_prefix=config.param_prefix,
|
@@ -441,7 +443,7 @@ def _create_iia_sdaqc(
|
|
441
443
|
entangler = config.strategy_args.get("entangler", CNOT)
|
442
444
|
periodic = config.strategy_args.get("periodic", False)
|
443
445
|
|
444
|
-
return
|
446
|
+
return iia(
|
445
447
|
n_qubits=num_qubits,
|
446
448
|
depth=config.depth,
|
447
449
|
param_prefix=config.param_prefix,
|
qadence/ml_tools/trainer.py
CHANGED
@@ -281,6 +281,7 @@ class Trainer(BaseTrainer):
|
|
281
281
|
self.device: torch_device | None = device
|
282
282
|
self.dtype: torch_dtype | None = dtype
|
283
283
|
self.data_dtype: torch_dtype | None = None
|
284
|
+
self.stop_training: bool = False
|
284
285
|
if self.dtype:
|
285
286
|
self.data_dtype = float64 if (self.dtype == complex128) else float32
|
286
287
|
|
@@ -321,6 +322,7 @@ class Trainer(BaseTrainer):
|
|
321
322
|
The callback_manager.start_training takes care of loading checkpoint,
|
322
323
|
and setting up the writer.
|
323
324
|
"""
|
325
|
+
self.stop_training = False
|
324
326
|
self.config_manager.initialize_config()
|
325
327
|
self.callback_manager.start_training(trainer=self)
|
326
328
|
|
@@ -377,25 +379,26 @@ class Trainer(BaseTrainer):
|
|
377
379
|
for epoch in range(
|
378
380
|
self.global_step, self.global_step + self.config_manager.config.max_iter + 1
|
379
381
|
):
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
self.
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
382
|
+
if not self.stop_training:
|
383
|
+
try:
|
384
|
+
self.current_epoch = epoch
|
385
|
+
self.on_train_epoch_start()
|
386
|
+
train_epoch_loss_metrics = self.run_training(self.train_dataloader)
|
387
|
+
train_losses.append(train_epoch_loss_metrics)
|
388
|
+
self.on_train_epoch_end(train_epoch_loss_metrics)
|
389
|
+
|
390
|
+
# Run validation periodically if specified
|
391
|
+
if self.perform_val and self.current_epoch % self.config.val_every == 0:
|
392
|
+
self.on_val_epoch_start()
|
393
|
+
val_epoch_loss_metrics = self.run_validation(self.val_dataloader)
|
394
|
+
val_losses.append(val_epoch_loss_metrics)
|
395
|
+
self.on_val_epoch_end(val_epoch_loss_metrics)
|
396
|
+
self.progress.update(val_task, advance=1)
|
397
|
+
|
398
|
+
self.progress.update(train_task, advance=1)
|
399
|
+
except KeyboardInterrupt:
|
400
|
+
logger.info("Terminating training gracefully after the current iteration.")
|
401
|
+
break
|
399
402
|
|
400
403
|
self.on_train_end(train_losses, val_losses)
|
401
404
|
return train_losses
|
@@ -629,10 +632,12 @@ class Trainer(BaseTrainer):
|
|
629
632
|
|
630
633
|
def build_optimize_result(
|
631
634
|
self,
|
632
|
-
result:
|
633
|
-
|
634
|
-
|
635
|
-
|
635
|
+
result: (
|
636
|
+
None
|
637
|
+
| tuple[torch.Tensor, dict[Any, Any]]
|
638
|
+
| list[tuple[torch.Tensor, dict[Any, Any]]]
|
639
|
+
| list[list[tuple[torch.Tensor, dict[Any, Any]]]]
|
640
|
+
),
|
636
641
|
) -> None:
|
637
642
|
"""
|
638
643
|
Builds and stores the optimization result by calculating the average loss and metrics.
|
@@ -119,9 +119,7 @@ class MCRX(ParametricControlBlock):
|
|
119
119
|
|
120
120
|
@property
|
121
121
|
def eigenvalues_generator(self) -> Tensor:
|
122
|
-
return torch.cat(
|
123
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
124
|
-
)
|
122
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
125
123
|
|
126
124
|
@property
|
127
125
|
def eigenvalues(self) -> Tensor:
|
@@ -164,9 +162,7 @@ class MCRY(ParametricControlBlock):
|
|
164
162
|
|
165
163
|
@property
|
166
164
|
def eigenvalues_generator(self) -> Tensor:
|
167
|
-
return torch.cat(
|
168
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
169
|
-
)
|
165
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
170
166
|
|
171
167
|
@property
|
172
168
|
def eigenvalues(self) -> Tensor:
|
@@ -205,9 +201,7 @@ class MCRZ(ParametricControlBlock):
|
|
205
201
|
|
206
202
|
@property
|
207
203
|
def eigenvalues_generator(self) -> Tensor:
|
208
|
-
return torch.cat(
|
209
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
210
|
-
)
|
204
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
211
205
|
|
212
206
|
@property
|
213
207
|
def eigenvalues(self) -> Tensor:
|