-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinfidelity.py
More file actions
160 lines (129 loc) · 5.17 KB
/
Copy pathinfidelity.py
File metadata and controls
160 lines (129 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import copy
from netket.utils.types import PyTree
from netket.vqs import VariationalState
from netket.logging import RuntimeLog
from netket.operator import AbstractOperator
from advanced_drivers._src.driver.abstract_variational_driver import (
AbstractVariationalDriver,
)
from advanced_drivers._src.callbacks.progressbar import ProgressBarCallback
from ptvmc._src.compression.abstract_compression import (
AbstractStateCompression,
CompressionState,
CompressionResultT,
)
class InfidelityCompression(AbstractStateCompression):
r"""
Compression algorithm based on the minimisation of the Infidelity.
Internally uses a driver of type `driver_class` to perform the compression, constructed
with the parameters `build_parameters` and whose execution is controlled by the parameters
`run_parameters`.
This is used by Schroedinger's equation solver to perform an implicit step, i.e. to compute
the state :math:`\ket{\psi(t+\Delta t)}` from the state :math:`\ket{\psi(t)}` as
.. math::
\ket{\psi(t+\Delta t)} = \hat{V}^{-1}\hat{U}\ket{\psi(t)}
where :math:`\hat{U}` and :math:`\hat{V}` are given by the particular discretization
scheme used by the solver.
"""
def __init__(
self,
driver_class: AbstractVariationalDriver,
build_parameters: PyTree,
run_parameters: PyTree,
):
r"""
Constructs the compression algorithm with the given parameters.
The driver will be constructed by calling the following function
.. code-block:: python
driver = driver_class(
target_state=tstate,
variational_state=copy.copy(vstate),
U=U,
V=V,
**build_parameters
)
# and executed with the parameters
driver.run(n_iter, out=logger, callback=callback, show_progress=False, **run_parameters)
A reasonable example of Infidelity Compression is given by
.. code-block:: python
import advanced_drivers as advd
import ptvmc
import optax
compression_alg = ptvmc.compression.InfidelityCompression(
driver_class=advd.driver.InfidelityOptimizerNG,
build_parameters={
"diag_shift": 1e-6,
"optimizer": optax.inject_hyperparams(optax.sgd)(learning_rate=0.05),
"linear_solver_fn": cholesky,
"proj_reg": None,
"momentum": None,
"chunk_size_bwd": None,
"collect_quadratic_model": False,
"use_ntk": False,
"cv_coeff": -0.5,
"resample_fraction": None,
"estimator": "cmc",
},
run_parameters={
"n_iter": 50,
"callback": [],
},
)
Args:
driver_class: The driver class to use for the compression. This must be a subclass
of :class:`advanced_drivers.driver.AbstractVariationalDriver`. The driver will be
constructed as discussed above.
build_parameters: a dictionary of keyword arguments to pass to the driver constructor.
run_parameters: a dictionary of keyword arguments to pass to the driver's `run` method.
"""
self.driver_class = driver_class
self._build_parameters = build_parameters
self._run_parameters = run_parameters
if "n_iter" not in run_parameters:
raise RuntimeError("Must specify the `n_iter` run parameter.")
@property
def build_parameters(self) -> PyTree:
"""Get the compression parameters."""
return self._build_parameters
@property
def run_parameters(self) -> PyTree:
"""Get the compression parameters."""
return self._run_parameters
def init_state(
self,
vstate: VariationalState,
tstate: VariationalState,
U: AbstractOperator,
V: AbstractOperator,
) -> CompressionState:
driver = self.driver_class(
target_state=tstate,
variational_state=copy.copy(vstate),
U=U,
V=V,
**self.build_parameters,
)
return driver
def execute(self, driver: CompressionState) -> CompressionResultT:
logger = RuntimeLog()
kwargs = self.run_parameters.copy()
n_iter = kwargs.pop("n_iter")
callback = kwargs.pop("callback")
if callback is None:
callback = []
elif not isinstance(callback, (list, tuple)):
callback = [callback]
else:
# this creates a copy
callback = list(callback)
progress_cb = ProgressBarCallback(n_iter, leave=False)
callback.append(progress_cb)
driver.run(
n_iter,
out=logger,
callback=callback,
show_progress=False,
**kwargs,
_graceful_keyboard_interrupt=False,
)
return driver.state, driver, logger.data