dense-evolution 8.3.0__py3-none-win_amd64.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.
- dashboard_core/__init__.py +115 -0
- dashboard_core/_gate_tables.py +30 -0
- dashboard_core/band_structure.py +71 -0
- dashboard_core/circuit_builder_component.py +232 -0
- dashboard_core/circuit_diagram.py +216 -0
- dashboard_core/crypto_protocols.py +77 -0
- dashboard_core/engine.py +326 -0
- dashboard_core/graphical_builder.py +114 -0
- dashboard_core/hamiltonians.py +593 -0
- dashboard_core/mass_decomposition_tool.py +47 -0
- dashboard_core/mitigation.py +343 -0
- dashboard_core/native_hf_diagnostics.py +62 -0
- dashboard_core/noise_tools.py +125 -0
- dashboard_core/qasm_library.py +233 -0
- dashboard_core/qmmm.py +16 -0
- dashboard_core/rag_tool.py +45 -0
- dashboard_core/state_visuals.py +288 -0
- dashboard_core/system_limits.py +60 -0
- dashboard_core/vector_healing.py +102 -0
- dashboard_core/visuals.py +158 -0
- dashboard_core/vqe.py +533 -0
- dashboard_core/wormhole.py +580 -0
- dense_evolution/__init__.py +114 -0
- dense_evolution/autodiff.py +10 -0
- dense_evolution/backends/__init__.py +5 -0
- dense_evolution/backends/chunk/__init__.py +37 -0
- dense_evolution/backends/chunk/_engine_imports.py +57 -0
- dense_evolution/backends/chunk/circuit_chunker.py +55 -0
- dense_evolution/backends/chunk/core.py +432 -0
- dense_evolution/backends/chunk/disk_overflow.py +232 -0
- dense_evolution/backends/chunk/geometry.py +95 -0
- dense_evolution/backends/chunk/guard.py +190 -0
- dense_evolution/backends/chunk/kernels.py +531 -0
- dense_evolution/backends/mps.py +1569 -0
- dense_evolution/backends/statevector.py +616 -0
- dense_evolution/chunk.py +25 -0
- dense_evolution/circuits/__init__.py +20 -0
- dense_evolution/circuits/compiler.py +488 -0
- dense_evolution/circuits/diagram.py +94 -0
- dense_evolution/circuits/gates.py +91 -0
- dense_evolution/circuits/parser.py +632 -0
- dense_evolution/circuits/qft.py +66 -0
- dense_evolution/circuits/random_circuit.py +85 -0
- dense_evolution/circuits/registry.py +74 -0
- dense_evolution/circuits/topology.py +79 -0
- dense_evolution/circuits/trotter.py +265 -0
- dense_evolution/circuits/uccsd.py +275 -0
- dense_evolution/cli.py +199 -0
- dense_evolution/compiler.py +9 -0
- dense_evolution/config.py +49 -0
- dense_evolution/drawing.py +10 -0
- dense_evolution/entropy.py +9 -0
- dense_evolution/fermions.py +9 -0
- dense_evolution/gates.py +9 -0
- dense_evolution/harrison_tb.py +16 -0
- dense_evolution/healing.py +18 -0
- dense_evolution/interop/__init__.py +18 -0
- dense_evolution/interop/qiskit_pennylane.py +406 -0
- dense_evolution/measurement.py +10 -0
- dense_evolution/mitigation/__init__.py +54 -0
- dense_evolution/mitigation/healing.py +215 -0
- dense_evolution/mitigation/kl_divergence.py +93 -0
- dense_evolution/mitigation/magic_entropy.py +163 -0
- dense_evolution/mitigation/magic_entropy_shadows.py +262 -0
- dense_evolution/mitigation/renyi.py +168 -0
- dense_evolution/mitigation/stabilizer_renyi_entropy.py +103 -0
- dense_evolution/mitigation/zne.py +990 -0
- dense_evolution/mps.py +9 -0
- dense_evolution/native_hf/__init__.py +26 -0
- dense_evolution/native_hf/_libcint/LICENSE-libcint +10 -0
- dense_evolution/native_hf/_libcint/libdecint.dll +0 -0
- dense_evolution/native_hf/assembly.py +304 -0
- dense_evolution/native_hf/basis.py +117 -0
- dense_evolution/native_hf/boys.py +35 -0
- dense_evolution/native_hf/bridge.py +112 -0
- dense_evolution/native_hf/cartesian.py +64 -0
- dense_evolution/native_hf/coulomb.py +196 -0
- dense_evolution/native_hf/differentiable.py +53 -0
- dense_evolution/native_hf/gaussians.py +79 -0
- dense_evolution/native_hf/kinetic.py +52 -0
- dense_evolution/native_hf/libcint_bridge.py +167 -0
- dense_evolution/native_hf/overlap.py +91 -0
- dense_evolution/native_hf/scf.py +404 -0
- dense_evolution/noise/__init__.py +79 -0
- dense_evolution/noise/coherent_attack.py +264 -0
- dense_evolution/noise/cosmic_ray.py +61 -0
- dense_evolution/noise/density_matrix_channels.py +78 -0
- dense_evolution/noise/differentiable.py +66 -0
- dense_evolution/noise/kraus/__init__.py +6 -0
- dense_evolution/noise/kraus/amplitude_damping.py +47 -0
- dense_evolution/noise/kraus/bitflip.py +22 -0
- dense_evolution/noise/kraus/combined.py +16 -0
- dense_evolution/noise/kraus/depolarizing.py +47 -0
- dense_evolution/noise/kraus/ideal.py +10 -0
- dense_evolution/noise/kraus/phaseflip.py +21 -0
- dense_evolution/noise/kraus_channels.py +285 -0
- dense_evolution/noise/oscillating.py +32 -0
- dense_evolution/noise/pink.py +80 -0
- dense_evolution/observables.py +11 -0
- dense_evolution/parser.py +9 -0
- dense_evolution/physics/__init__.py +27 -0
- dense_evolution/physics/entropy.py +161 -0
- dense_evolution/physics/fermions.py +322 -0
- dense_evolution/physics/observables.py +523 -0
- dense_evolution/physics/qec.py +1113 -0
- dense_evolution/physics/spectral.py +143 -0
- dense_evolution/physics/states.py +43 -0
- dense_evolution/protocols/__init__.py +27 -0
- dense_evolution/protocols/bb84.py +133 -0
- dense_evolution/protocols/di_qkd_ghz.py +199 -0
- dense_evolution/protocols/dicka_protocol2.py +124 -0
- dense_evolution/qec.py +20 -0
- dense_evolution/qft.py +9 -0
- dense_evolution/qmmm/__init__.py +13 -0
- dense_evolution/qmmm/ase_bridge.py +97 -0
- dense_evolution/qmmm/forces.py +388 -0
- dense_evolution/qmmm/propagation.py +80 -0
- dense_evolution/qmmm/region.py +137 -0
- dense_evolution/random_circuit.py +15 -0
- dense_evolution/registry.py +9 -0
- dense_evolution/simulator.py +10 -0
- dense_evolution/solvers/__init__.py +19 -0
- dense_evolution/solvers/autodiff.py +169 -0
- dense_evolution/solvers/harrison_tb.py +189 -0
- dense_evolution/solvers/vhd_tb.py +187 -0
- dense_evolution/states.py +9 -0
- dense_evolution/topology.py +9 -0
- dense_evolution/trotter.py +9 -0
- dense_evolution/utils/__init__.py +13 -0
- dense_evolution/utils/drawing.py +101 -0
- dense_evolution/utils/mass_decomposition.py +246 -0
- dense_evolution/utils/measurement.py +94 -0
- dense_evolution/vhd_tb.py +16 -0
- dense_evolution-8.3.0.dist-info/METADATA +366 -0
- dense_evolution-8.3.0.dist-info/RECORD +165 -0
- dense_evolution-8.3.0.dist-info/WHEEL +5 -0
- dense_evolution-8.3.0.dist-info/entry_points.txt +2 -0
- dense_evolution-8.3.0.dist-info/licenses/license.md +58 -0
- dense_evolution-8.3.0.dist-info/top_level.txt +5 -0
- ia_utils/__init__.py +0 -0
- ia_utils/adversarial_vector_attack.py +196 -0
- ia_utils/rag.py +288 -0
- ia_utils/vector_healing.py +399 -0
- local_site/__init__.py +0 -0
- local_site/app/__init__.py +0 -0
- local_site/app/server.py +1009 -0
- mcp_server/__init__.py +0 -0
- mcp_server/client.py +324 -0
- mcp_server/config.py +32 -0
- mcp_server/models.py +347 -0
- mcp_server/molecules.py +71 -0
- mcp_server/server.py +119 -0
- mcp_server/tools/__init__.py +0 -0
- mcp_server/tools/chemistry_tools.py +225 -0
- mcp_server/tools/circuit_tools.py +83 -0
- mcp_server/tools/crypto_tools.py +66 -0
- mcp_server/tools/mitigation_tools.py +81 -0
- mcp_server/tools/noise_tools.py +60 -0
- mcp_server/tools/retrieval_tools.py +44 -0
- mcp_server/tools/system_tools.py +149 -0
- mcp_server/tools/wormhole_tools.py +142 -0
- mcp_server/utils/__init__.py +0 -0
- mcp_server/utils/cache.py +55 -0
- mcp_server/utils/images.py +67 -0
- mcp_server/utils/truncation.py +38 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Overlap integrals between Gaussian shells via the Obara-Saika recursion.
|
|
2
|
+
|
|
3
|
+
For two 1D Gaussians centered at A, B with exponents a, b, let
|
|
4
|
+
p = a+b and P = (aA+bB)/p be the center of their product (Gaussian
|
|
5
|
+
product theorem). The overlap S[i,j] = <(x-A)^i exp(-a(x-A)^2) |
|
|
6
|
+
(x-B)^j exp(-b(x-B)^2)> obeys two recursions:
|
|
7
|
+
|
|
8
|
+
Vertical (build up the first index from the base case S[0,0]):
|
|
9
|
+
S[i,0] = (P-A) S[i-1,0] + (i-1)/(2p) S[i-2,0]
|
|
10
|
+
|
|
11
|
+
Horizontal (build up the second index by shifting angular momentum
|
|
12
|
+
from center A to center B, exact for any two centers -- this is why
|
|
13
|
+
it needs no exponent-dependent term):
|
|
14
|
+
S[i,j] = (A-B) S[i,j-1] + S[i+1,j-1]
|
|
15
|
+
|
|
16
|
+
Both are linear recursions in one index with a 2-term memory, so each
|
|
17
|
+
maps directly onto jax.lax.scan: the whole angular-momentum ladder for
|
|
18
|
+
a shell pair compiles to one XLA loop instead of a Python for-loop.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import functools
|
|
22
|
+
|
|
23
|
+
import jax
|
|
24
|
+
import jax.numpy as jnp
|
|
25
|
+
|
|
26
|
+
from dense_evolution.native_hf.gaussians import (
|
|
27
|
+
GaussianShell1D,
|
|
28
|
+
GaussianShell3D,
|
|
29
|
+
product_center,
|
|
30
|
+
product_prefactor,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _base_overlap_1d(g1: GaussianShell1D, g2: GaussianShell1D) -> jax.Array:
|
|
35
|
+
p = g1.exponent + g2.exponent
|
|
36
|
+
mu = (g1.exponent * g2.exponent) / p
|
|
37
|
+
K = jnp.exp(-mu * jnp.square(g1.center - g2.center))
|
|
38
|
+
return jnp.sqrt(jnp.pi / p) * K
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _vertical_step(p_minus_a, inv_two_p, carry, i):
|
|
42
|
+
s_prev, s_prev2 = carry
|
|
43
|
+
s_next = p_minus_a * s_prev + (i - 1) * inv_two_p * s_prev2
|
|
44
|
+
return (s_next, s_prev), s_next
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _build_first_index(s00, g1: GaussianShell1D, g2: GaussianShell1D, n_extra: int) -> jax.Array:
|
|
48
|
+
"""Returns S[i, 0] for i = 0..n_extra."""
|
|
49
|
+
if n_extra == 0:
|
|
50
|
+
return s00[None]
|
|
51
|
+
p = g1.exponent + g2.exponent
|
|
52
|
+
P = (g1.exponent * g1.center + g2.exponent * g2.center) / p
|
|
53
|
+
step = functools.partial(_vertical_step, P - g1.center, 1.0 / (2.0 * p))
|
|
54
|
+
_, rest = jax.lax.scan(step, (s00, jnp.zeros_like(s00)), jnp.arange(1, n_extra + 1))
|
|
55
|
+
return jnp.concatenate([s00[None], rest])
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _horizontal_step(a_minus_b, column, _):
|
|
59
|
+
shifted = jnp.roll(column, shift=-1)
|
|
60
|
+
new_column = a_minus_b * column + shifted
|
|
61
|
+
return new_column, new_column
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _build_second_index(first_col: jax.Array, g1: GaussianShell1D, g2: GaussianShell1D) -> jax.Array:
|
|
65
|
+
"""first_col holds S[:,0]. Returns S[:, 0..g2.degree] (rows beyond
|
|
66
|
+
validity are garbage and get sliced away by the caller)."""
|
|
67
|
+
if g2.degree == 0:
|
|
68
|
+
return first_col[:, None]
|
|
69
|
+
step = functools.partial(_horizontal_step, g1.center - g2.center)
|
|
70
|
+
_, rest = jax.lax.scan(step, first_col, jnp.arange(1, g2.degree + 1))
|
|
71
|
+
return jnp.concatenate([first_col[:, None], jnp.moveaxis(rest, 0, -1)], axis=-1)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def overlap_1d(g1: GaussianShell1D, g2: GaussianShell1D) -> jax.Array:
|
|
75
|
+
"""S[i,j] for 0<=i<=g1.degree, 0<=j<=g2.degree. Shape (g1.degree+1, g2.degree+1)."""
|
|
76
|
+
s00 = _base_overlap_1d(g1, g2)
|
|
77
|
+
first_col = _build_first_index(s00, g1, g2, g1.degree + g2.degree)
|
|
78
|
+
full = _build_second_index(first_col, g1, g2)
|
|
79
|
+
return full[: g1.degree + 1, :]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@jax.jit
|
|
83
|
+
def overlap_3d(g1: GaussianShell3D, g2: GaussianShell3D) -> jax.Array:
|
|
84
|
+
"""S[ix,iy,iz,jx,jy,jz] for the full Cartesian shell pair.
|
|
85
|
+
|
|
86
|
+
Shape: (L1+1,L1+1,L1+1, L2+1,L2+1,L2+1) where L1, L2 are the shell
|
|
87
|
+
degrees (unphysical (i,j,k) combinations with i+j+k > degree are
|
|
88
|
+
simply never read by the caller).
|
|
89
|
+
"""
|
|
90
|
+
axes = [overlap_1d(g1.component(d), g2.component(d)) for d in range(3)]
|
|
91
|
+
return jnp.einsum("ad,be,cf->abcdef", *axes)
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
"""Restricted Hartree-Fock self-consistent field loop (Roothaan-Hall).
|
|
2
|
+
|
|
3
|
+
Standard textbook algorithm (e.g. Szabo & Ostlund, "Modern Quantum
|
|
4
|
+
Chemistry", ch. 3): orthogonalize the AO basis via S^(-1/2), build the
|
|
5
|
+
Fock matrix F = H_core + 2J - K from the current density, diagonalize
|
|
6
|
+
in the orthogonal basis, form a new density, repeat to convergence.
|
|
7
|
+
This part is genuinely simple compared to the integral evaluation and
|
|
8
|
+
doesn't need vectorizing -- a closed-shell molecule's SCF loop is a few
|
|
9
|
+
dozen matrix multiplies on an N x N matrix where N is a few tens at
|
|
10
|
+
most for STO-3G, nowhere near where PennyLane's implementation loses
|
|
11
|
+
its time (which is entirely in building H_core/repulsion tensor, done
|
|
12
|
+
once in assembly.py, not in this loop).
|
|
13
|
+
|
|
14
|
+
BUG FOUND (Si2, minimal 4-electron/4-orbital active space, R=2.184 A):
|
|
15
|
+
plain (undamped) density substitution never converged for this system
|
|
16
|
+
-- 100/100 iterations, still oscillating -- because two pairs of
|
|
17
|
+
orbitals near the active-space boundary are numerically degenerate
|
|
18
|
+
(HOMO-1/HOMO and LUMO/LUMO+1 each split by <1e-9 Ha), so each iteration
|
|
19
|
+
flips which member of a near-tied pair gets occupied, and the density
|
|
20
|
+
never settles. Confirmed this is a real oscillation, not just slow
|
|
21
|
+
convergence: three separate machines/runs of the undamped loop each
|
|
22
|
+
hit the iteration cap at a DIFFERENT total energy (-571.63, -570.69,
|
|
23
|
+
-571.02 Ha), all physically meaningless artifacts of whatever step the
|
|
24
|
+
loop happened to be on. First fixed with plain linear density damping
|
|
25
|
+
(P_next = alpha*P_new + (1-alpha)*P_old) -- textbook remedy for exactly
|
|
26
|
+
this oscillation failure mode (Szabo & Ostlund ch. 3.4.9), verified to
|
|
27
|
+
converge to the SAME energy (-570.874032094871 Ha, agreeing to 10
|
|
28
|
+
significant figures) across alpha in {0.1, 0.2, 0.3, 0.5, 0.7).
|
|
29
|
+
|
|
30
|
+
UPGRADED to DIIS (Pulay, "Convergence acceleration of iterative
|
|
31
|
+
sequences: the case of SCF iteration", Chem. Phys. Lett. 73, 393
|
|
32
|
+
(1980); "Improved SCF convergence acceleration", J. Comput. Chem. 3,
|
|
33
|
+
556 (1982)) -- the standard production-grade SCF accelerator plain
|
|
34
|
+
linear damping is a simplified special case of. Pulay's own error
|
|
35
|
+
vector, `e = X.T @ (F@P@S - S@P@F) @ X` (the Fock/density commutator in
|
|
36
|
+
the orthonormal basis, exactly zero at true self-consistency), is kept
|
|
37
|
+
across the last `diis_dim` iterations alongside the Fock matrices that
|
|
38
|
+
produced them; each step extrapolates a new Fock matrix as the
|
|
39
|
+
minimum-norm linear combination of that history (constrained to sum to
|
|
40
|
+
1) instead of diagonalizing the latest F directly. Verified on the
|
|
41
|
+
same Si2 near-degenerate case that motivated damping in the first
|
|
42
|
+
place: DIIS converges in 11 iterations to -570.8740320948958 Ha, versus
|
|
43
|
+
53 iterations for plain damped substitution alone (diis_dim=0,
|
|
44
|
+
alpha=0.5) to reach the same energy, -570.8740320948963 Ha -- agreeing
|
|
45
|
+
to 12 significant figures, the same true self-consistent solution
|
|
46
|
+
reached ~4.8x faster, not a different answer.
|
|
47
|
+
|
|
48
|
+
If the DIIS linear system is ever singular (a degenerate/duplicated
|
|
49
|
+
error-vector history), that step falls back to the plain, unextrapolated
|
|
50
|
+
Fock matrix rather than raising -- a transient fallback, not silent
|
|
51
|
+
wrong physics, since the next iteration's fresh error vector rebuilds a
|
|
52
|
+
usable history.
|
|
53
|
+
|
|
54
|
+
Convergence now requires BOTH the density AND the energy to stop
|
|
55
|
+
changing (`|P_new - P| < convergence_tol` AND `|E_new - E_old| <
|
|
56
|
+
energy_tol`) rather than density alone -- density convergence can
|
|
57
|
+
occasionally plateau one step before energy does (or vice versa) for
|
|
58
|
+
a system with several nearly-degenerate iterations near the end of the
|
|
59
|
+
run; requiring both is strictly more conservative than either alone
|
|
60
|
+
and costs at most a couple of extra iterations on every system tested
|
|
61
|
+
here.
|
|
62
|
+
|
|
63
|
+
Rewritten from NumPy to jax.numpy (the integral-building side in
|
|
64
|
+
assembly.py already was JAX; this loop and its np.array() outputs were
|
|
65
|
+
the only remaining barrier to an end-to-end JAX-traced pipeline). The
|
|
66
|
+
iteration itself uses jax.lax.while_loop for its data-dependent
|
|
67
|
+
convergence check, same as the original Python for/break -- note that
|
|
68
|
+
reverse-mode autodiff (jax.grad) does not work through while_loop, by
|
|
69
|
+
JAX's own design (the number of iterations isn't known ahead of time,
|
|
70
|
+
which reverse-mode differentiation needs). Making this loop's OUTPUT
|
|
71
|
+
differentiable is a separate, deliberately deferred step: the correct
|
|
72
|
+
approach is implicit differentiation at the fixed point (the custom
|
|
73
|
+
gradient rule only needs the converged F/P, not a replay of every
|
|
74
|
+
iteration), not unrolling this loop and backpropagating through it.
|
|
75
|
+
|
|
76
|
+
DIIS history is now a fixed-size (diis_dim, n, n) ring buffer instead
|
|
77
|
+
of a growing/shrinking Python list -- jax.lax.while_loop requires its
|
|
78
|
+
carried state to have constant shape across iterations. Each step
|
|
79
|
+
rolls the buffer and writes the newest Fock/error matrix into the last
|
|
80
|
+
slot; a boolean mask (derived from how many iterations have actually
|
|
81
|
+
run) excludes the not-yet-filled slots from the DIIS linear system
|
|
82
|
+
instead of the original's list-length check. The original's
|
|
83
|
+
try/except LinAlgError fallback becomes a jnp.isfinite check on the
|
|
84
|
+
solved coefficients (a singular solve produces NaN/Inf under JAX
|
|
85
|
+
rather than raising), selecting the single latest Fock matrix exactly
|
|
86
|
+
as the original's except-branch did.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
import dataclasses
|
|
90
|
+
import functools
|
|
91
|
+
|
|
92
|
+
import jax
|
|
93
|
+
import numpy as np
|
|
94
|
+
import jax.numpy as jnp
|
|
95
|
+
|
|
96
|
+
from dense_evolution.config import ensure_x64
|
|
97
|
+
|
|
98
|
+
_DIIS_DIM = 8
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclasses.dataclass
|
|
102
|
+
class HFResult:
|
|
103
|
+
converged: bool
|
|
104
|
+
n_iterations: int
|
|
105
|
+
electronic_energy: float
|
|
106
|
+
nuclear_repulsion_energy: float
|
|
107
|
+
total_energy: float
|
|
108
|
+
orbital_energies: jax.Array
|
|
109
|
+
orbital_coefficients: jax.Array # C, shape (n_basis, n_basis)
|
|
110
|
+
density_matrix: jax.Array
|
|
111
|
+
energy_history: jax.Array # shape (max_iterations,), NaN past n_iterations
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def nuclear_repulsion_energy(nuclear_charges: list[float], nuclear_positions: jax.Array) -> jax.Array:
|
|
115
|
+
positions = jnp.asarray(nuclear_positions)
|
|
116
|
+
energy = 0.0
|
|
117
|
+
n = len(nuclear_charges)
|
|
118
|
+
for i in range(n):
|
|
119
|
+
for j in range(i + 1, n):
|
|
120
|
+
r = jnp.linalg.norm(positions[i] - positions[j])
|
|
121
|
+
energy = energy + nuclear_charges[i] * nuclear_charges[j] / r
|
|
122
|
+
return energy
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _orthogonalizer(S: jax.Array) -> jax.Array:
|
|
126
|
+
w, v = jnp.linalg.eigh(S)
|
|
127
|
+
return v @ jnp.diag(1.0 / jnp.sqrt(w)) @ v.T
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _density_from_coefficients(C: jax.Array, n_occupied_pairs: int) -> jax.Array:
|
|
131
|
+
C_occ = C[:, :n_occupied_pairs]
|
|
132
|
+
return C_occ @ C_occ.T
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _diis_error(F: jax.Array, P: jax.Array, S: jax.Array, X: jax.Array) -> jax.Array:
|
|
136
|
+
"""Pulay's DIIS error vector, `X.T @ (F@P@S - S@P@F) @ X` -- the
|
|
137
|
+
Fock/density commutator (zero at true self-consistency, since F and
|
|
138
|
+
P then commute), transformed into the same orthonormal basis the
|
|
139
|
+
Fock matrix itself is diagonalized in. F, P, S are all symmetric, so
|
|
140
|
+
this reduces to `Y - Y.T` for `Y = X.T @ F @ P @ S @ X` -- computed
|
|
141
|
+
that way to avoid forming two separate FPS/SPF products."""
|
|
142
|
+
Y = X.T @ F @ P @ S @ X
|
|
143
|
+
return Y - Y.T
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _diis_extrapolate(fock_history: jax.Array, error_history: jax.Array, history_count: jax.Array, diis_dim: int) -> jax.Array:
|
|
147
|
+
"""fock_history/error_history: (diis_dim, n, n), newest entry always
|
|
148
|
+
in the last slot (see run_scf's roll-and-append). `valid` marks
|
|
149
|
+
which of the diis_dim slots hold a real (not yet overwritten, not a
|
|
150
|
+
zero-initialized placeholder) entry -- the last `history_count` of
|
|
151
|
+
them. Invalid slots are pinned to c_i=0 by giving their row/column
|
|
152
|
+
of the augmented linear system an identity-like equation instead of
|
|
153
|
+
a real DIIS constraint, so they can't contribute to the solution
|
|
154
|
+
regardless of their (garbage/zero) content."""
|
|
155
|
+
dtype = fock_history.dtype
|
|
156
|
+
zero = jnp.zeros((), dtype=dtype)
|
|
157
|
+
one = jnp.ones((), dtype=dtype)
|
|
158
|
+
valid = jnp.arange(diis_dim) >= (diis_dim - history_count)
|
|
159
|
+
|
|
160
|
+
errs_flat = error_history.reshape(diis_dim, -1)
|
|
161
|
+
B_full = errs_flat @ errs_flat.T
|
|
162
|
+
mask2d = valid[:, None] & valid[None, :]
|
|
163
|
+
B = jnp.where(mask2d, B_full, zero)
|
|
164
|
+
B = jnp.where(jnp.eye(diis_dim, dtype=bool) & ~mask2d, one, B)
|
|
165
|
+
|
|
166
|
+
A = jnp.zeros((diis_dim + 1, diis_dim + 1), dtype=dtype)
|
|
167
|
+
A = A.at[:diis_dim, :diis_dim].set(B)
|
|
168
|
+
col = jnp.where(valid, -one, zero)
|
|
169
|
+
A = A.at[:diis_dim, diis_dim].set(col)
|
|
170
|
+
A = A.at[diis_dim, :diis_dim].set(col)
|
|
171
|
+
b = jnp.zeros(diis_dim + 1, dtype=dtype).at[diis_dim].set(-one)
|
|
172
|
+
|
|
173
|
+
solution = jnp.linalg.solve(A, b)
|
|
174
|
+
is_finite = jnp.all(jnp.isfinite(solution))
|
|
175
|
+
coeffs = jnp.where(valid, jnp.where(is_finite, solution[:diis_dim], zero), zero)
|
|
176
|
+
|
|
177
|
+
F_diis = jnp.tensordot(coeffs, fock_history, axes=1)
|
|
178
|
+
return jnp.where(is_finite, F_diis, fock_history[-1])
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _level_shift_fock(F_ao: jax.Array, C_prev: jax.Array, S: jax.Array, n_occupied_pairs: int, level_shift: float) -> jax.Array:
|
|
182
|
+
"""Saunders & Hillier level shifting (Int. J. Quantum Chem. 7, 699
|
|
183
|
+
(1973)): push the virtual orbitals of the PREVIOUS iteration's MO
|
|
184
|
+
basis up by `level_shift` before this iteration's diagonalization,
|
|
185
|
+
to open a numerical gap and stop the occupied/virtual split from
|
|
186
|
+
flip-flopping across a near-degeneracy (see this module's own Si2
|
|
187
|
+
docstring above -- damping/DIIS already fix the textbook case, but a
|
|
188
|
+
real, harder case (a 30-atom aromatic fragment from the CASMI26
|
|
189
|
+
wiring kernel) still took 1114 iterations, swinging through three
|
|
190
|
+
wildly different intermediate energies first). Exact no-op at
|
|
191
|
+
level_shift=0.0: since C_prev is a full, S-orthonormal basis
|
|
192
|
+
(C_prev.T @ S @ C_prev = I, hence C_prev @ C_prev.T = S^{-1}), the
|
|
193
|
+
round-trip S @ C_prev @ (C_prev.T @ F_ao @ C_prev) @ C_prev.T @ S
|
|
194
|
+
reduces algebraically to exactly F_ao before any shift is added."""
|
|
195
|
+
F_mo_prev = C_prev.T @ F_ao @ C_prev
|
|
196
|
+
n = F_mo_prev.shape[0]
|
|
197
|
+
level_shift = jnp.asarray(level_shift, dtype=F_ao.dtype)
|
|
198
|
+
shift_diag = jnp.where(jnp.arange(n) >= n_occupied_pairs, level_shift, jnp.zeros((), dtype=F_ao.dtype))
|
|
199
|
+
F_mo_prev_shifted = F_mo_prev + jnp.diag(shift_diag)
|
|
200
|
+
return S @ C_prev @ F_mo_prev_shifted @ C_prev.T @ S
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def run_scf(
|
|
204
|
+
S: jax.Array,
|
|
205
|
+
H_core: jax.Array,
|
|
206
|
+
repulsion: jax.Array,
|
|
207
|
+
n_electrons: int,
|
|
208
|
+
nuclear_charges: list[float],
|
|
209
|
+
nuclear_positions: jax.Array,
|
|
210
|
+
max_iterations: int = 200,
|
|
211
|
+
convergence_tol: float = 1e-10,
|
|
212
|
+
energy_tol: float = 1e-10,
|
|
213
|
+
damping: float = 0.5,
|
|
214
|
+
diis_dim: int = _DIIS_DIM,
|
|
215
|
+
level_shift: float = 0.0,
|
|
216
|
+
) -> HFResult:
|
|
217
|
+
ensure_x64()
|
|
218
|
+
if n_electrons % 2 != 0:
|
|
219
|
+
raise ValueError("Only closed-shell (even electron count) systems are supported.")
|
|
220
|
+
n_occupied_pairs = n_electrons // 2
|
|
221
|
+
n_basis = S.shape[0]
|
|
222
|
+
|
|
223
|
+
X = _orthogonalizer(S)
|
|
224
|
+
orbital_energies0, C_ortho0 = jnp.linalg.eigh(X.T @ H_core @ X)
|
|
225
|
+
C0 = X @ C_ortho0
|
|
226
|
+
P0 = _density_from_coefficients(C0, n_occupied_pairs)
|
|
227
|
+
|
|
228
|
+
def _fock_and_energy(P):
|
|
229
|
+
J = jnp.einsum("pqrs,rs->pq", repulsion, P)
|
|
230
|
+
K = jnp.einsum("prqs,rs->pq", repulsion, P)
|
|
231
|
+
F = H_core + 2.0 * J - K
|
|
232
|
+
energy = jnp.sum(P * (H_core + F))
|
|
233
|
+
return F, energy
|
|
234
|
+
|
|
235
|
+
def cond_fun(state):
|
|
236
|
+
iteration, _P, _C, _orbital_energies, _energy_prev, converged, _fock_history, _error_history, _energy_history = state
|
|
237
|
+
return jnp.logical_and(jnp.logical_not(converged), iteration < max_iterations)
|
|
238
|
+
|
|
239
|
+
def body_fun(state):
|
|
240
|
+
iteration, P, C_prev, _orbital_energies, energy_prev, _converged, fock_history, error_history, energy_history = state
|
|
241
|
+
|
|
242
|
+
F, energy = _fock_and_energy(P)
|
|
243
|
+
error = _diis_error(F, P, S, X)
|
|
244
|
+
|
|
245
|
+
fock_history = jnp.roll(fock_history, shift=-1, axis=0).at[-1].set(F)
|
|
246
|
+
error_history = jnp.roll(error_history, shift=-1, axis=0).at[-1].set(error)
|
|
247
|
+
history_count = jnp.minimum(iteration + 1, diis_dim)
|
|
248
|
+
|
|
249
|
+
F_step = jnp.where(
|
|
250
|
+
history_count >= 2,
|
|
251
|
+
_diis_extrapolate(fock_history, error_history, history_count, diis_dim),
|
|
252
|
+
F,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
F_diag = _level_shift_fock(F_step, C_prev, S, n_occupied_pairs, level_shift)
|
|
256
|
+
orbital_energies, C_ortho = jnp.linalg.eigh(X.T @ F_diag @ X)
|
|
257
|
+
C = X @ C_ortho
|
|
258
|
+
P_new = _density_from_coefficients(C, n_occupied_pairs)
|
|
259
|
+
|
|
260
|
+
density_converged = jnp.linalg.norm(P_new - P) < convergence_tol
|
|
261
|
+
energy_converged = jnp.abs(energy - energy_prev) < energy_tol
|
|
262
|
+
converged = jnp.logical_and(density_converged, energy_converged)
|
|
263
|
+
|
|
264
|
+
P_damped = jnp.where(history_count < 2, damping * P_new + (1.0 - damping) * P, P_new)
|
|
265
|
+
P_next = jnp.where(converged, P_new, P_damped)
|
|
266
|
+
|
|
267
|
+
energy_history = energy_history.at[iteration].set(energy)
|
|
268
|
+
|
|
269
|
+
return (iteration + 1, P_next, C, orbital_energies, energy, converged, fock_history, error_history, energy_history)
|
|
270
|
+
|
|
271
|
+
init_state = (
|
|
272
|
+
jnp.array(0),
|
|
273
|
+
P0,
|
|
274
|
+
C0,
|
|
275
|
+
orbital_energies0,
|
|
276
|
+
jnp.array(jnp.inf, dtype=H_core.dtype),
|
|
277
|
+
jnp.array(False),
|
|
278
|
+
jnp.zeros((diis_dim, n_basis, n_basis), dtype=H_core.dtype),
|
|
279
|
+
jnp.zeros((diis_dim, n_basis, n_basis), dtype=H_core.dtype),
|
|
280
|
+
jnp.full((max_iterations,), jnp.nan, dtype=H_core.dtype),
|
|
281
|
+
)
|
|
282
|
+
iteration, P, C, orbital_energies, _energy_prev, converged, _fh, _eh, energy_history = jax.lax.while_loop(cond_fun, body_fun, init_state)
|
|
283
|
+
|
|
284
|
+
_F, electronic_energy = _fock_and_energy(P)
|
|
285
|
+
e_nuc = nuclear_repulsion_energy(nuclear_charges, nuclear_positions)
|
|
286
|
+
|
|
287
|
+
return HFResult(
|
|
288
|
+
converged=bool(converged),
|
|
289
|
+
n_iterations=int(iteration),
|
|
290
|
+
electronic_energy=float(electronic_energy),
|
|
291
|
+
nuclear_repulsion_energy=float(e_nuc),
|
|
292
|
+
total_energy=float(electronic_energy) + float(e_nuc),
|
|
293
|
+
orbital_energies=orbital_energies,
|
|
294
|
+
orbital_coefficients=C,
|
|
295
|
+
density_matrix=P,
|
|
296
|
+
energy_history=energy_history,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _import_dense_armor_robust_filters():
|
|
301
|
+
try:
|
|
302
|
+
from dense_armor.utility.robust_filters import hampel_filter, tukey_fences
|
|
303
|
+
except ImportError as exc:
|
|
304
|
+
raise ImportError(
|
|
305
|
+
"native_hf.scf.diagnose_convergence needs Dense-Armor (pip install dense-evolution[armor])"
|
|
306
|
+
) from exc
|
|
307
|
+
return hampel_filter, tukey_fences
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def diagnose_convergence(result: HFResult, radius: int = 5, n_sigmas: float = 3.0) -> dict:
|
|
311
|
+
"""Real automatic guard on HFResult.energy_history, instead of trusting
|
|
312
|
+
the final `converged` flag in isolation: Dense-Armor's Hampel filter
|
|
313
|
+
and Tukey fences (dense_evolution.utility.robust_filters -- the sister
|
|
314
|
+
project's own anomaly detectors, Chauvenet/Tukey/Hampel/sigma-clipping,
|
|
315
|
+
validated with 0 false positives on real H2 dissociation-curve
|
|
316
|
+
chemistry) applied to the real per-iteration electronic energy trace.
|
|
317
|
+
|
|
318
|
+
Validated on a real non-converging case (a 28-heavy-atom CASMI26
|
|
319
|
+
fragment, level_shift=0.0): the broken run flags 19-24% of its 200
|
|
320
|
+
iterations as anomalous; the same fragment fixed with level_shift=0.5
|
|
321
|
+
(converges in 55 iterations) flags only ~4% -- background noise, not a
|
|
322
|
+
false-alarm storm. Needs the `armor` extra (pip install
|
|
323
|
+
dense-evolution[armor]) -- Dense-Armor is not a hard dependency of this
|
|
324
|
+
module."""
|
|
325
|
+
hampel_filter, tukey_fences = _import_dense_armor_robust_filters()
|
|
326
|
+
trace = np.asarray(result.energy_history[:result.n_iterations])
|
|
327
|
+
n = max(1, result.n_iterations)
|
|
328
|
+
|
|
329
|
+
_cleaned_h, anomalies_h = hampel_filter(trace, radius=radius, n_sigmas=n_sigmas)
|
|
330
|
+
_cleaned_t, anomalies_t = tukey_fences(trace, radius=len(trace))
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
"n_iterations": result.n_iterations,
|
|
334
|
+
"n_anomalies_hampel": len(anomalies_h),
|
|
335
|
+
"n_anomalies_tukey": len(anomalies_t),
|
|
336
|
+
"anomaly_fraction_hampel": len(anomalies_h) / n,
|
|
337
|
+
"anomaly_fraction_tukey": len(anomalies_t) / n,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@functools.partial(jax.custom_vjp, nondiff_argnums=(3,))
|
|
342
|
+
def scf_electronic_energy(S: jax.Array, H_core: jax.Array, repulsion: jax.Array, n_electrons: int) -> jax.Array:
|
|
343
|
+
"""The RHF electronic energy (run_scf's own `electronic_energy`, not
|
|
344
|
+
counting nuclear repulsion) as a function of S/H_core/repulsion that
|
|
345
|
+
IS differentiable via jax.grad -- unlike run_scf itself, whose
|
|
346
|
+
jax.lax.while_loop can't be traced in reverse mode.
|
|
347
|
+
|
|
348
|
+
The gradient is NOT backprop through the SCF iteration (which
|
|
349
|
+
wouldn't even be possible) -- it's the analytic Hartree-Fock gradient
|
|
350
|
+
of Pople, Krishnan, Schlegel & Binkley, Int. J. Quantum Chem. Symp.
|
|
351
|
+
13, 225 (1979), eq. (21)-(22): at self-consistency, dE/dtheta equals
|
|
352
|
+
the derivative of `Tr[P(H_core+F(P))] - Tr[W S]` with P and the
|
|
353
|
+
energy-weighted density matrix W held fixed at their converged
|
|
354
|
+
values (an envelope-theorem/Lagrangian result -- P and W are the
|
|
355
|
+
stationary point and multipliers of the constrained HF variational
|
|
356
|
+
problem, so their own dependence on theta drops out of the total
|
|
357
|
+
derivative). W is built from ONLY the occupied orbitals:
|
|
358
|
+
`W = C_occ @ diag(2 * orbital_energies_occ) @ C_occ.T` -- the factor
|
|
359
|
+
of 2 is this module's own P convention (no explicit 2 in P itself,
|
|
360
|
+
carried instead by F = H_core + 2J - K), not part of Pople et al.'s
|
|
361
|
+
original spin-orbital formula. This automatically
|
|
362
|
+
includes the "Pulay force" terms from the atom-centered basis moving
|
|
363
|
+
with the nuclei (via H_core/repulsion/S's own theta-dependence),
|
|
364
|
+
without hand-deriving them -- jax.grad on the frozen-P expression
|
|
365
|
+
below does that part for free.
|
|
366
|
+
|
|
367
|
+
Verified against central finite differences on H2/STO-3G (see
|
|
368
|
+
tests/unit/test_native_hf_differentiable.py)."""
|
|
369
|
+
result = run_scf(S, H_core, repulsion, n_electrons, [], jnp.zeros((0, 3)))
|
|
370
|
+
return result.electronic_energy
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def _scf_electronic_energy_fwd(S, H_core, repulsion, n_electrons):
|
|
374
|
+
result = run_scf(S, H_core, repulsion, n_electrons, [], jnp.zeros((0, 3)))
|
|
375
|
+
residuals = (S, H_core, repulsion, result.density_matrix, result.orbital_coefficients, result.orbital_energies)
|
|
376
|
+
return result.electronic_energy, residuals
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _scf_electronic_energy_bwd(n_electrons, residuals, cotangent):
|
|
380
|
+
S, H_core, repulsion, P, C, orbital_energies = residuals
|
|
381
|
+
n_occupied_pairs = n_electrons // 2
|
|
382
|
+
C_occ = C[:, :n_occupied_pairs]
|
|
383
|
+
# Lagrange multiplier for the C_occ.T @ S @ C_occ = I constraint is
|
|
384
|
+
# 2*diag(orbital_energies_occ), not diag(orbital_energies_occ) --
|
|
385
|
+
# this module's P has no explicit factor of 2 (F = H_core + 2J - K
|
|
386
|
+
# carries it instead), so stationarity of Tr[P(H_core+F(P))] -
|
|
387
|
+
# Tr[Lambda(C_occ.T S C_occ - I)] w.r.t. C_occ gives F C_occ =
|
|
388
|
+
# S C_occ (Lambda/2), which must match the Roothaan-Hall equation
|
|
389
|
+
# F C_occ = S C_occ diag(eps_occ) -- so Lambda = 2*diag(eps_occ).
|
|
390
|
+
# Verified: omitting this factor of 2 gave a gradient that disagreed
|
|
391
|
+
# with central finite differences by exactly Tr[W_undoubled dS/dx].
|
|
392
|
+
W = C_occ @ jnp.diag(2.0 * orbital_energies[:n_occupied_pairs]) @ C_occ.T
|
|
393
|
+
|
|
394
|
+
def lagrangian(S_, H_core_, repulsion_):
|
|
395
|
+
J = jnp.einsum("pqrs,rs->pq", repulsion_, P)
|
|
396
|
+
K = jnp.einsum("prqs,rs->pq", repulsion_, P)
|
|
397
|
+
F = H_core_ + 2.0 * J - K
|
|
398
|
+
return jnp.sum(P * (H_core_ + F)) - jnp.sum(W * S_)
|
|
399
|
+
|
|
400
|
+
dS, dH_core, drepulsion = jax.grad(lagrangian, argnums=(0, 1, 2))(S, H_core, repulsion)
|
|
401
|
+
return (cotangent * dS, cotangent * dH_core, cotangent * drepulsion)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
scf_electronic_energy.defvjp(_scf_electronic_energy_fwd, _scf_electronic_energy_bwd)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Every way to put noise into a Dense-Evolution simulation, in one place.
|
|
2
|
+
|
|
3
|
+
- **`NoiseModel`** (`.kraus_channels`, dispatching to one file per channel
|
|
4
|
+
under `.kraus`: `ideal`, `depolarizing`, `bitflip`, `phaseflip`,
|
|
5
|
+
`amplitude_damping`, `combined`) -- 6 stochastic single-qubit Kraus
|
|
6
|
+
channels, applied directly to a statevector via `apply_to_sv`.
|
|
7
|
+
- **`NoiseSpec`** (`.differentiable`) -- the native JAX-differentiable
|
|
8
|
+
representation of a noise configuration, so noise strength itself can be
|
|
9
|
+
a traced/differentiable value inside `circuit_to_energy_fn`.
|
|
10
|
+
- **Coherent adversarial noise** (`.coherent_attack`) -- a genuinely
|
|
11
|
+
continuous, multi-qubit coherent error channel (`apply_rz_all`) and a
|
|
12
|
+
JAX-differentiable search (`craft_adversarial_delta`,
|
|
13
|
+
`craft_adversarial_delta_constrained`) for a worst-case direction against
|
|
14
|
+
a stabilizer code's syndrome -- promoted from Dense-Evolution-Discovery's
|
|
15
|
+
Steane [[7,1,3]] investigation, including its honest negative result
|
|
16
|
+
(see `coherent_attack`'s module docstring).
|
|
17
|
+
- **Density-matrix channels** (`.density_matrix_channels`) --
|
|
18
|
+
`global_depolarizing_channel`, `amplitude_damping_channel`: noise applied
|
|
19
|
+
directly to a density matrix instead of a statevector, for density-matrix
|
|
20
|
+
ZNE's noise ensemble. `phaseflip_channel_exact`: the same phaseflip model
|
|
21
|
+
as `NoiseModel`'s `'phaseflip'` statevector Kraus channel, but computed as
|
|
22
|
+
its exact zero-sampling-variance limit directly on a density matrix, for
|
|
23
|
+
use as a "classical node" in Classically Augmented ZNE (see
|
|
24
|
+
`dense_evolution.mitigation.classically_augmented_zne_phaseflip`).
|
|
25
|
+
- **`cosmic_ray_burst_profile`** (`.cosmic_ray`) -- a real, time-dependent
|
|
26
|
+
noise-strength profile for a cosmic-ray-induced quasiparticle burst.
|
|
27
|
+
- **`oscillating_p_eff`** (`.oscillating`) -- a noise strength that
|
|
28
|
+
oscillates instead of scaling smoothly, for stress-testing mitigation
|
|
29
|
+
techniques that assume smoothness.
|
|
30
|
+
- **`pink_noise_p_eff`** (`.pink`) -- a noise-strength trace with a real
|
|
31
|
+
1/f (pink/flicker) power spectrum, the dominant decoherence mechanism
|
|
32
|
+
in real superconducting qubits, via the Timmer & Koenig (1995)
|
|
33
|
+
spectral-synthesis algorithm.
|
|
34
|
+
|
|
35
|
+
Real device noise from a Qiskit backend's own calibration data
|
|
36
|
+
(`noise_model_from_qiskit_backend`) lives in `dense_evolution.interop`,
|
|
37
|
+
not here, since it needs a Qiskit `BackendV2` object as input rather than
|
|
38
|
+
a noise-specific dependency.
|
|
39
|
+
|
|
40
|
+
Everything in this package previously lived scattered across
|
|
41
|
+
`dense_evolution.circuits.registry` (alongside unrelated hardware-detection
|
|
42
|
+
code) and `dense_evolution.mitigation.zne` (alongside unrelated mitigation
|
|
43
|
+
techniques, which only ever cancel noise, never generate it). Both modules
|
|
44
|
+
re-export the relevant names from here for backward compatibility, but
|
|
45
|
+
`dense_evolution.noise` is the canonical import path for new code.
|
|
46
|
+
"""
|
|
47
|
+
from .kraus_channels import NoiseModel
|
|
48
|
+
from .differentiable import NoiseSpec
|
|
49
|
+
from .coherent_attack import (
|
|
50
|
+
apply_rz_all,
|
|
51
|
+
x_stabilizer_leakage,
|
|
52
|
+
craft_adversarial_delta,
|
|
53
|
+
project_l2_linf,
|
|
54
|
+
craft_adversarial_delta_constrained,
|
|
55
|
+
decoder_failure_rate,
|
|
56
|
+
random_delta_failure_stats,
|
|
57
|
+
)
|
|
58
|
+
from .density_matrix_channels import global_depolarizing_channel, amplitude_damping_channel, phaseflip_channel_exact
|
|
59
|
+
from .cosmic_ray import cosmic_ray_burst_profile
|
|
60
|
+
from .oscillating import oscillating_p_eff
|
|
61
|
+
from .pink import pink_noise_p_eff
|
|
62
|
+
|
|
63
|
+
__all__ = [
|
|
64
|
+
"NoiseModel",
|
|
65
|
+
"NoiseSpec",
|
|
66
|
+
"apply_rz_all",
|
|
67
|
+
"x_stabilizer_leakage",
|
|
68
|
+
"craft_adversarial_delta",
|
|
69
|
+
"project_l2_linf",
|
|
70
|
+
"craft_adversarial_delta_constrained",
|
|
71
|
+
"decoder_failure_rate",
|
|
72
|
+
"random_delta_failure_stats",
|
|
73
|
+
"global_depolarizing_channel",
|
|
74
|
+
"amplitude_damping_channel",
|
|
75
|
+
"phaseflip_channel_exact",
|
|
76
|
+
"cosmic_ray_burst_profile",
|
|
77
|
+
"oscillating_p_eff",
|
|
78
|
+
"pink_noise_p_eff",
|
|
79
|
+
]
|