Skip to content

Commit d5414c6

Browse files
committed
clean structure
1 parent 859aa5a commit d5414c6

19 files changed

Lines changed: 2221 additions & 281 deletions

.github/workflows/release.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Release CD (Safe)
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
inputs:
9+
publish_to_testpypi:
10+
description: "Publish to TestPyPI"
11+
type: boolean
12+
default: false
13+
publish_to_pypi:
14+
description: "Publish to PyPI"
15+
type: boolean
16+
default: false
17+
18+
permissions:
19+
contents: read
20+
id-token: write
21+
22+
concurrency:
23+
group: release-${{ github.ref }}
24+
cancel-in-progress: false
25+
26+
jobs:
27+
build_dist:
28+
name: Build + Validate Artifacts
29+
runs-on: ubuntu-latest
30+
outputs:
31+
version: ${{ steps.meta.outputs.version }}
32+
steps:
33+
- name: Check out source
34+
uses: actions/checkout@v4
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.11"
40+
41+
- name: Install build tools
42+
run: |
43+
python -m pip install --upgrade pip
44+
pip install build twine
45+
46+
- name: Build sdist and wheel
47+
run: python -m build
48+
49+
- name: Validate package metadata
50+
run: twine check dist/*
51+
52+
- name: Capture package version
53+
id: meta
54+
run: |
55+
VERSION=$(python -c "import pepsy; print(pepsy.__version__)")
56+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
57+
58+
- name: Upload artifacts
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: pepsy-dist-${{ steps.meta.outputs.version }}
62+
path: dist/*
63+
64+
publish_testpypi:
65+
name: Publish to TestPyPI
66+
needs: build_dist
67+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi }}
68+
runs-on: ubuntu-latest
69+
environment: testpypi
70+
steps:
71+
- name: Download artifacts
72+
uses: actions/download-artifact@v4
73+
with:
74+
name: pepsy-dist-${{ needs.build_dist.outputs.version }}
75+
path: dist
76+
77+
- name: Publish
78+
uses: pypa/gh-action-pypi-publish@release/v1
79+
with:
80+
repository-url: https://test.pypi.org/legacy/
81+
82+
publish_pypi:
83+
name: Publish to PyPI
84+
needs: build_dist
85+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi }}
86+
runs-on: ubuntu-latest
87+
environment: pypi
88+
steps:
89+
- name: Download artifacts
90+
uses: actions/download-artifact@v4
91+
with:
92+
name: pepsy-dist-${{ needs.build_dist.outputs.version }}
93+
path: dist
94+
95+
- name: Publish
96+
uses: pypa/gh-action-pypi-publish@release/v1

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
<img src="assets/pepsy-icon.svg" alt="pepsy icon" width="220" />
44

5-
`pepsy` is a Python package for boundary-MPS based PEPS norm contraction and related DMRG fitting workflows.
5+
`pepsy` is a Python package for Circuit Simulaiton and related DMRG fitting workflows.
66

7-
Current package version: `0.0.1` (from `pepsy/VERSION`).
7+
Current package version: `0.1.0` (from `pepsy/VERSION`).
88

99
## Package Layout
1010
- `pepsy/`: installable library code
@@ -20,11 +20,11 @@ Current package version: `0.0.1` (from `pepsy/VERSION`).
2020
```bash
2121
python -m venv .venv
2222
source .venv/bin/activate
23-
pip install -r requirements.txt
2423
pip install -e .
2524
# Optional backends:
2625
# pip install -e .[torch]
2726
# pip install -e .[jax]
27+
# pip install -e .[solvers]
2828
```
2929

3030
## Quick Usage

docs/howto/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ Task-oriented references for common operational questions.
66
:maxdepth: 2
77
88
choose_parameters
9+
solver_tuning
910
troubleshooting
1011
```

docs/howto/solver_tuning.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# How-To: Tune Sweep Solvers
2+
3+
Use `PEPSSweepOptimizer.optimize_axis(...)` or `optimize_global(...)` with `solver` and `solver_options`.
4+
5+
## Quick comparison
6+
7+
- `solver="adam"`: best default for noisy or sensitive objectives.
8+
- `solver="lbfgs"`: defaults to SciPy `L-BFGS-B` in sweep APIs.
9+
- `solver="torch-lbfgs"`: torch-native quasi-Newton, often faster near convergence.
10+
- `solver="scipy-lbfgs"`: robust CPU `L-BFGS-B`, supports bounds.
11+
- `solver="nlopt-lbfgs"`: flexible stopping controls and algorithm variants.
12+
13+
## Recipe: Torch LBFGS
14+
15+
```python
16+
result = sweeper.optimize_global(
17+
axes=("y", "x"),
18+
n_cycles=1,
19+
n_round_trips=1,
20+
solver="torch-lbfgs",
21+
solver_options={
22+
"max_iter": 1, # one inner LBFGS step per outer sweep step
23+
"history_size": 20,
24+
"line_search_fn": "strong_wolfe",
25+
},
26+
lr=1.0,
27+
n_steps=60,
28+
log_every=20,
29+
env_n_iter=4,
30+
pbar=True,
31+
)
32+
```
33+
34+
Practical notes:
35+
36+
- Keep `max_iter=1` so `n_steps` remains the main outer control knob.
37+
- Start with `lr=1.0`; reduce if updates oscillate.
38+
39+
## Recipe: SciPy L-BFGS-B
40+
41+
```python
42+
result = sweeper.optimize_global(
43+
axes=("y", "x"),
44+
n_cycles=1,
45+
n_round_trips=1,
46+
solver="scipy-lbfgs",
47+
solver_options={
48+
"method": "L-BFGS-B",
49+
"maxiter": 80,
50+
"ftol": 1e-12,
51+
},
52+
n_steps=80,
53+
log_every=20,
54+
env_n_iter=4,
55+
pbar=True,
56+
)
57+
```
58+
59+
Practical notes:
60+
61+
- This backend optimizes on CPU `float64` vectors internally.
62+
- You can set bounds with either `bounds=[(lo, hi), ...]` or `lower_bounds` / `upper_bounds`.
63+
64+
## Recipe: NLopt LBFGS
65+
66+
```python
67+
result = sweeper.optimize_global(
68+
axes=("y", "x"),
69+
n_cycles=1,
70+
n_round_trips=1,
71+
solver="nlopt-lbfgs",
72+
solver_options={
73+
"algorithm": "LD_LBFGS",
74+
"maxeval": 100,
75+
"ftol_rel": 1e-10,
76+
"xtol_rel": 1e-10,
77+
},
78+
n_steps=100,
79+
log_every=20,
80+
env_n_iter=4,
81+
pbar=True,
82+
)
83+
```
84+
85+
Practical notes:
86+
87+
- `maxeval` is the main NLopt iteration cap.
88+
- If needed, switch `algorithm` to another NLopt gradient method.
89+
- This path is more sensitive to stopping settings; for a robust default start from `scipy-lbfgs`.
90+
91+
## Best-parameter behavior
92+
93+
All sweep solvers now return and apply the **best-loss parameters** seen during the run, not just the last iterate. This is important for non-monotonic trajectories.
94+
95+
## Numerical stability and backend transitions
96+
97+
- External solvers (`scipy-lbfgs`, `nlopt-lbfgs`) flatten params to CPU NumPy `float64`.
98+
- Complex parameters are split into real/imag blocks during optimization and reconstructed afterward.
99+
- Returned parameters are cast back to original tensor dtype/device before being applied to the PEPS state.
100+
101+
This design keeps optimizer interoperability while minimizing conversion-induced drift.

pepsy/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
boundary_sweeps,
1313
core,
1414
dmrg_fit,
15+
gradient_solver,
1516
optimize_sweep,
1617
)
1718
from .boundary_norm import (
@@ -25,6 +26,8 @@
2526
from .core import (
2627
get_default_array_backend,
2728
get_default_grad_backend,
29+
register_jax_linalg,
30+
register_torch_linalg,
2831
reset_default_backends,
2932
set_default_array_backend,
3033
set_default_grad_backend,
@@ -44,10 +47,13 @@
4447
"get_default_array_backend",
4548
"set_default_grad_backend",
4649
"get_default_grad_backend",
50+
"register_torch_linalg",
51+
"register_jax_linalg",
4752
"reset_default_backends",
4853
"PEPSSweepOptimizer",
4954
"SweepResult",
5055
"optimize_sweep",
56+
"gradient_solver",
5157
"boundary_norm",
5258
"boundary_states",
5359
"boundary_sweeps",
@@ -61,6 +67,7 @@ def __getattr__(name):
6167
"boundary_norm",
6268
"boundary_states",
6369
"boundary_sweeps",
70+
"gradient_solver",
6471
"optimize_sweep",
6572
"core",
6673
"dmrg_fit",
@@ -98,11 +105,15 @@ def __getattr__(name):
98105
"get_default_array_backend",
99106
"set_default_grad_backend",
100107
"get_default_grad_backend",
108+
"register_torch_linalg",
109+
"register_jax_linalg",
101110
"reset_default_backends",
102111
):
103112
from .core import ( # pylint: disable=import-outside-toplevel
104113
get_default_array_backend,
105114
get_default_grad_backend,
115+
register_jax_linalg,
116+
register_torch_linalg,
106117
reset_default_backends,
107118
set_default_array_backend,
108119
set_default_grad_backend,
@@ -113,6 +124,8 @@ def __getattr__(name):
113124
"get_default_array_backend": get_default_array_backend,
114125
"set_default_grad_backend": set_default_grad_backend,
115126
"get_default_grad_backend": get_default_grad_backend,
127+
"register_torch_linalg": register_torch_linalg,
128+
"register_jax_linalg": register_jax_linalg,
116129
"reset_default_backends": reset_default_backends,
117130
}[name]
118131

0 commit comments

Comments
 (0)