Linear System Solvers
solve() is a unified entry point for and selects among HHL, QSVT, Schrödingerization, adiabatic, variational, and Chebyshev Krylov methods.
Minimal example
import numpy as np
from unitarylab.library import solve
A = np.array([[2.0, 1.0], [1.0, 3.0]])
b = np.array([1.0, 0.0])
result = solve(A, b, method="hhl", d=6, backend="torch", device="cpu")
print(result.solution)
print(result.scaling_factor)Entry point and methods
solve(A, b, method="hhl", backend="torch", device="cpu",
dtype=np.complex128, precondition=None, **kwargs)| Method and aliases | Matrix requirements | Common method-specific parameters |
|---|---|---|
hhl | Hermitian | d=6, t=None, r=None, use_small_angle_approx=None |
qsvt, qsvt_qlsa | Hermitian | epsilon=0.001 |
schro, schro_trotter, schro_classical | Square; further requirements depend on the branch | Schrödingerization parameters |
aqc, discrete_adiabatic | Hermitian | Total adiabatic time and number of discrete steps |
vqls | Any square matrix | cost_function, n_layers, maxiter, tol, seed, epsilon |
cks | Hermitian | epsilon=0.01 |
A must be an square matrix; b must have length , and must be a power of two. Matrix and vector entries must be finite. A zero vector, singular matrix, or matrix that violates a method’s assumptions can be rejected or fail to produce a valid solution.
Method defaults and branch selection
- HHL defaults to
d=6andt=None; leavingranduse_small_angle_approxunset lets the solver choose them. - QSVT defaults to
epsilon=0.001; CKS defaults toepsilon=0.01. - AQC defaults to
T=Noneandp=1.4, with the solver estimating the total number of steps. - VQLS defaults to
cost_function="global",n_layers=16,maxiter=50000,tol=1e-6,seed=None, andepsilon=None. It also supportsn_restarts=1,optimizer="L-BFGS-B", andglobal_cost_stop=None. These differ from the Algorithms library’sVQLSAlgorithm.run()defaults oflocal_ht, 4 layers, 500 iterations, andseed=42. - Schrödingerization defaults to
T=10.0,na=6,R=4.0,order=2,point=1,type="classical", anddt=None. Theschro_trotterandschro_classicalentry names are aliases for the same dispatch; the actual branch is selected bytype, not the method name alone.
Preconditioning
precondition accepts:
| Value | Behavior | Guidance |
|---|---|---|
None | No preprocessing | Default |
diagonal / jacobi | Symmetric diagonal scaling | Preserves Hermiticity |
symmetric / ic | Symmetric incomplete Cholesky | For positive-definite matrices; preserves Hermiticity |
ilu | Incomplete LU splitting | Can break Hermiticity; use cautiously with HHL/QSVT/AQC |
After preprocessing, .solution is restored to the coordinates of the original problem. The transformed problem is stored in .matrix and .rhs; original inputs are stored in .matrix_original and .rhs_original.
Return value
LinearSolverResult has these fields:
| Field | Description |
|---|---|
solution | Approximate solution vector |
matrix, rhs | Problem actually passed to the solver |
circuit | Algorithm circuit; may be None for a purely classical branch |
scaling_factor | Factor for recovering solution amplitude from a normalized quantum state |
precondition_mode | Preprocessing information or None |
matrix_original, rhs_original | Original inputs when preprocessing was used |
Low-level HHLSolver, QSVTSolver, SCHROSolver, AQCSolver, VQLSSolver, and CKSSolver can be imported from unitarylab.library.linear_solver. They all return (circuit, solution, scaling_factor). Direct low-level calls do not include the preprocessing metadata from the high-level result object.
Usage recommendations
- Use
np.linalg.solve(A, b)to check a small-scale baseline and residual. - Method-specific parameters are forwarded through
**kwargs; do not pass a method’s parameters to another method. - Increasing phase precision, circuit depth, or polynomial precision increases resource use and does not necessarily improve finite-precision results monotonically.
- Set
seedexplicitly for reproducible randomized workflows such as VQLS.