Skip to content
Open

tmp #232

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
8064acf
Update Project.toml and various problem templates to use knot points …
aarontrowbridge Oct 28, 2025
46135da
Refactor quantum problem templates to use N instead of T for time ste…
aarontrowbridge Oct 28, 2025
041efd8
Refactor time step references in problem templates and constraints to…
aarontrowbridge Oct 29, 2025
32dde14
Refactor control variable naming and initialization in quantum contro…
aarontrowbridge Oct 29, 2025
3583093
Documentation Template Refactor (#213)
jack-champagne Aug 13, 2025
d8cde7c
add julia 1.12 to test matrix (#216)
jack-champagne Oct 29, 2025
81c920c
Update docs: change control variable from 'a' to 'u' everywhere
aarontrowbridge Oct 29, 2025
40fc114
Add Problem Templates Overview documentation page
aarontrowbridge Oct 29, 2025
64c0445
Add comprehensive solution handling and options documentation
aarontrowbridge Oct 29, 2025
d9b4579
Fix documentation build errors
aarontrowbridge Oct 29, 2025
de09376
Fix QuantumSystem constructor calls with T_max and drive_bounds
aarontrowbridge Oct 29, 2025
b944d37
Fix problem template constructor signatures in docs
aarontrowbridge Oct 29, 2025
60855df
Fix two qubit gates example to use correct API signatures
aarontrowbridge Oct 29, 2025
303ceff
Rename T to N for number of timesteps in two qubit gates example
aarontrowbridge Oct 29, 2025
de94233
Fix multilevel transmon example to use N and correct problem signature
aarontrowbridge Oct 29, 2025
bffd021
Rename T to N for timesteps in all man page examples
aarontrowbridge Oct 29, 2025
ed8ed09
Fix GATES access to use dot notation instead of bracket indexing
aarontrowbridge Oct 29, 2025
735f0de
Remove u_bound kwarg - bounds are specified in QuantumSystem
aarontrowbridge Oct 29, 2025
0df8a1f
Remove u_bound kwarg from all problem templates - use system.drive_bo…
aarontrowbridge Oct 29, 2025
d1ab285
Add quick start guide to index with installation and 30-second example
aarontrowbridge Oct 29, 2025
580e65b
Add single qubit Hadamard gate canonical example
aarontrowbridge Oct 29, 2025
1d4ca38
Add minimum time optimization example
aarontrowbridge Oct 29, 2025
3365383
Add robust control sampling example
aarontrowbridge Oct 29, 2025
ec23984
Update solve! function calls to include options for IpoptOptions
aarontrowbridge Oct 29, 2025
f173fb8
Add documentation for custom objectives, constraints, and initial tra…
aarontrowbridge Oct 29, 2025
98d735e
Merge branch 'main' into dev/quantum-system-refactor
jack-champagne Oct 29, 2025
da4f44b
Fix robust times parameter in UnitaryVariationalProblem example
aarontrowbridge Oct 29, 2025
122e655
Fix variable name from T to N in UnitarySamplingProblem and UnitaryVa…
aarontrowbridge Oct 29, 2025
35e55c7
Replace variable T with N in QuantumStateSamplingProblem and UnitaryS…
aarontrowbridge Oct 29, 2025
9d4d97f
Add convenience trajectory initialization functions
aarontrowbridge Oct 30, 2025
9689142
Add store_times parameter to trajectory initialization functions
aarontrowbridge Oct 31, 2025
b1cc10f
Add QuantumTrajectories module and implement trajectory types
aarontrowbridge Nov 3, 2025
b03a311
Add time-dependent handling for Unitary, Ket, and Density trajectories
aarontrowbridge Nov 7, 2025
00af4fa
Add quantum control problem templates and core functionality
aarontrowbridge Nov 7, 2025
7caa53a
Refactor constraints handling in apply_piccolo_options! and update ob…
aarontrowbridge Nov 10, 2025
7e06f48
Refactor SmoothPulseProblem and Integrators for Enhanced Flexibility …
aarontrowbridge Nov 30, 2025
35a1dea
Add EnsembleTrajectory support to SmoothPulseProblem for simultaneous…
aarontrowbridge Dec 11, 2025
453e73b
Remove unnecessary display of components in BilinearIntegrator test
aarontrowbridge Dec 18, 2025
71a7ff5
remove old templates and update tests for consistent passing
jack-champagne Dec 19, 2025
3f063ce
move test scripts from top-level to scripts folder
jack-champagne Dec 19, 2025
50a2290
Merge branch 'main' into feature/problem-template-redesign
jack-champagne Dec 19, 2025
8577e8b
Add EnsembleTrajectory support to MinimumTimeProblem and update sampl…
aarontrowbridge Dec 22, 2025
5916a09
Add TODO comment to ensure quantum trajectory is updated after solvin…
aarontrowbridge Dec 23, 2025
2a55e20
Refactor quantum control problem templates and enhance robust optimiz…
aarontrowbridge Jan 8, 2026
91b338d
Final fidelity constraint with ensemble
mabuni1998 Jan 8, 2026
6e1c65c
Merge branch 'feature/problem-template-redesign' of https://github.co…
mabuni1998 Jan 8, 2026
5e8794e
Remove unused final fidelity constraint function for EnsembleTrajecto…
aarontrowbridge Jan 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 240 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
# QuantumCollocation.jl Context

> AI-friendly context for maintaining consistency. Update this when making significant changes.

## Package Purpose

QuantumCollocation.jl provides **problem templates** for quantum optimal control using direct collocation. It builds on:
- **DirectTrajOpt.jl** - Core optimization infrastructure (objectives, constraints, integrators, NLP solver)
- **PiccoloQuantumObjects.jl** - Quantum systems, trajectories, pulses, and utilities
- **NamedTrajectories.jl** - Named variable trajectory data structure

The main abstractions are:
1. **QuantumControlProblem** - Wrapper combining quantum trajectory info with optimization problem
2. **Problem Templates** - Constructors that build complete optimization problems

## Canonical Workflow

### Basic Gate Synthesis

```julia
using QuantumCollocation
using PiccoloQuantumObjects

# 1. Define quantum system (no T_max - duration comes from trajectory)
H_drift = GATES[:Z]
H_drives = [GATES[:X], GATES[:Y]]
drive_bounds = [1.0, 1.0] # symmetric bounds
sys = QuantumSystem(H_drift, H_drives, drive_bounds)

# 2. Create quantum trajectory (defines the control problem)
U_goal = GATES[:H] # target: Hadamard gate
T = 10.0 # duration
qtraj = UnitaryTrajectory(sys, U_goal, T) # creates zero pulse internally

# 3. Build optimization problem
N = 51 # number of timesteps
qcp = SmoothPulseProblem(qtraj, N; Q=100.0, R=1e-2)

# 4. Solve
solve!(qcp; max_iter=200)

# 5. Extract results
traj = get_trajectory(qcp)
U_final = iso_vec_to_operator(traj[end][:Ũ⃗])
fid = unitary_fidelity(U_final, U_goal)
```

### State Transfer (Ket)

```julia
sys = QuantumSystem(H_drift, H_drives, drive_bounds)

ψ_init = ComplexF64[1.0, 0.0] # |0⟩
ψ_goal = ComplexF64[0.0, 1.0] # |1⟩
T = 10.0
qtraj = KetTrajectory(sys, ψ_init, ψ_goal, T)

qcp = SmoothPulseProblem(qtraj, N; Q=50.0, R=1e-3)
solve!(qcp; max_iter=100)
```

### Ensemble Control (Multiple Initial States)

```julia
sys = QuantumSystem(H_drift, H_drives, drive_bounds)

# X gate: |0⟩→|1⟩ and |1⟩→|0⟩
initials = [ComplexF64[1,0], ComplexF64[0,1]]
goals = [ComplexF64[0,1], ComplexF64[1,0]]
T = 10.0
qtraj = EnsembleKetTrajectory(sys, initials, goals, T)

qcp = SmoothPulseProblem(qtraj, N; Q=100.0, R=1e-2)
solve!(qcp; max_iter=200)
```

### With Explicit Pulse (Spline-Based)

```julia
sys = QuantumSystem(H_drift, H_drives, drive_bounds)

# Create explicit pulse with initial guess
T = 10.0
times = collect(range(0.0, T, length=N))
controls = 0.1 * randn(sys.n_drives, N)
pulse = LinearSplinePulse(controls, times)

qtraj = UnitaryTrajectory(sys, pulse, U_goal)

# Use SplinePulseProblem for spline pulses
qcp = SplinePulseProblem(qtraj, N; Q=100.0, R=1e-2, du_bound=10.0)
solve!(qcp; max_iter=200)
```

### Minimum Time Optimization

```julia
# First solve with fixed time
qcp = SmoothPulseProblem(qtraj, N; Q=100.0, Δt_bounds=(0.01, 0.5))
solve!(qcp; max_iter=100)

# Convert to minimum-time problem
qcp_mintime = MinimumTimeProblem(qcp; final_fidelity=0.99, D=50.0)
solve!(qcp_mintime; max_iter=100)
```

### Robust Control (Parameter Sampling)

```julia
# Create base problem
qtraj = UnitaryTrajectory(sys_nominal, pulse, U_goal)
qcp = SmoothPulseProblem(qtraj, N; Q=100.0)

# Add robustness over parameter variations
sampling_prob = SamplingProblem(qcp, [sys_nominal, sys_perturbed]; Q=100.0)
solve!(sampling_prob; max_iter=200)
```

## Key Abstractions

### Quantum Trajectories (defined in PiccoloQuantumObjects.jl)

Parametric type hierarchy (see PiccoloQuantumObjects.jl/CONTEXT.md for details):
```
AbstractQuantumTrajectory{P<:AbstractPulse}
├── UnitaryTrajectory{P} # Full unitary evolution
├── KetTrajectory{P} # Single state evolution
├── EnsembleKetTrajectory{P} # Multiple states, shared controls
├── DensityTrajectory{P} # Density matrix evolution (WIP)
└── SamplingTrajectory{P,Q} # Robustness over system parameters
```

QuantumCollocation.jl **uses** these types and provides problem templates that build on them.

### Problem Templates

| Template | Use Case | Pulse Type |
|----------|----------|------------|
| `SmoothPulseProblem` | Standard optimization with smooth pulses | `ZeroOrderPulse` (piecewise constant) |
| `SplinePulseProblem` | Spline-based pulse optimization | `LinearSplinePulse`, `CubicSplinePulse` |
| `MinimumTimeProblem` | Time-optimal control | Any (converts existing problem) |
| `SamplingProblem` | Robust control over parameters | Any (wraps existing problem) |

**SmoothPulseProblem** (for ZeroOrderPulse):
- Adds derivative variables `:du`, `:ddu` for smoothness
- Creates `DerivativeIntegrator` constraints enforcing `u[k+1] - u[k] = Δt * du[k]`
- Applies quadratic regularization on `u`, `du`, `ddu`

**SplinePulseProblem** (for spline pulses):
- For `LinearSplinePulse`: `:du` represents slopes (added automatically)
- For `CubicSplinePulse`: `:du` represents Hermite tangents (built into pulse)
- Uses `DerivativeIntegrator` with spline semantics

### Quantum Integrators (`quantum_integrators.jl`)

`BilinearIntegrator` dispatches on trajectory type:
```julia
BilinearIntegrator(qtraj::UnitaryTrajectory, N) # → single integrator
BilinearIntegrator(qtraj::KetTrajectory, N) # → single integrator
BilinearIntegrator(qtraj::EnsembleKetTrajectory, N) # → Vector of integrators
BilinearIntegrator(qtraj::SamplingTrajectory, N) # → Vector of integrators
```

**Signature pattern:** `(qtraj, N::Int)` - creates NamedTrajectory internally

### Quantum Constraints (`quantum_constraints.jl`)

Fidelity constraints for minimum-time problems:
- `FinalUnitaryFidelityConstraint(qtraj, traj, fidelity)`
- `FinalKetFidelityConstraint(qtraj, traj, fidelity)`
- `FinalCoherentKetFidelityConstraint(qtraj, traj, fidelity)` - For ensembles, preserves phase coherence

## Component Naming Conventions

| Component | Symbol | Description |
|-----------|--------|-------------|
| Unitary state | `:Ũ⃗` | Isomorphism-vectorized unitary |
| Ket state | `:ψ̃` | Isomorphism-vectorized ket |
| Ensemble kets | `:ψ̃1`, `:ψ̃2`, ... | Multiple states |
| Sampling states | `:Ũ⃗1`, `:Ũ⃗2`, ... | States for each system sample |
| Controls | `:u` | Pulse amplitudes (canonical name) |
| Control derivative | `:du` | First derivative / slope |
| Control 2nd derivative | `:ddu` | Second derivative / acceleration |
| Timestep | `:Δt` | Duration of each timestep |
| Time | `:t` | Accumulated time (always present) |

## Testing Conventions

Tests use `@testitem` blocks in source files:
```julia
@testitem "descriptive name" begin
using QuantumCollocation
using PiccoloQuantumObjects
using DirectTrajOpt
using LinearAlgebra
# ... test code
end
```

Run tests with `TestItemRunner.@run_package_tests`.

## Recent Changes (Update This!)

### January 2026
- Removed `time_dependent=true` from test QuantumSystem constructions (`:t` is now always in trajectories)
- Removed `adapt_trajectory`/`unadapt_trajectory` usage (control scaling removed)
- Updated `BilinearIntegrator` signatures from `(qtraj, traj)` to `(qtraj, N)`
- Added `FinalCoherentKetFidelityConstraint` for ensemble minimum-time problems

### Removed Patterns (Don't Reintroduce!)
- ❌ `adapt_trajectory` / `unadapt_trajectory` - Control scaling was removed
- ❌ `@test sys.time_dependent` in tests - Not needed since `:t` is always present
- ❌ `QuantumSystem(...; time_dependent=true)` in tests - Redundant
- ❌ Control name `:a` - Canonical control name is `:u`

## File Structure

```
src/
├── QuantumCollocation.jl # Main module, reexports
├── piccolo_options.jl # PiccoloOptions configuration
├── quantum_control_problem.jl # QuantumControlProblem wrapper
├── quantum_integrators.jl # BilinearIntegrator dispatch
├── quantum_constraints.jl # Fidelity constraints
├── quantum_objectives.jl # Fidelity objectives
└── problem_templates/
├── _problem_templates.jl # Submodule definition
├── smooth_pulse_problem.jl # ZeroOrderPulse optimization
├── spline_pulse_problem.jl # Spline pulse optimization
├── minimum_time_problem.jl # Time-optimal control
└── sampling_problem.jl # Robust control
```

## Common Gotchas

1. **Pulse type determines problem template**: Use `SmoothPulseProblem` for `ZeroOrderPulse`, `SplinePulseProblem` for spline pulses
2. **N is timesteps, not knot points**: For `N=51`, you get 50 intervals
3. **Trajectories always have `:t`**: Time is accumulated automatically, no need for `time_dependent` flag
4. **EnsembleKetTrajectory vs SamplingTrajectory**: Ensemble = same system, different initial states; Sampling = different systems, same initial state
5. **Fidelity vs Infidelity**: Objectives minimize infidelity, constraints bound infidelity (e.g., `1 - fidelity ≤ 1 - 0.99`)
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ TestItems = "1c621080-faea-4a02-84b6-bbd5e436b8fe"
TrajectoryIndexingUtils = "6dad8b7f-dd9a-4c28-9b70-85b9a079bfc8"

[compat]
DirectTrajOpt = "0.5"
DirectTrajOpt = "0.6"
Distributions = "0.25"
ExponentialAction = "0.2"
LinearAlgebra = "1.10, 1.11, 1.12"
NamedTrajectories = "0.6"
PiccoloQuantumObjects = "0.7"
NamedTrajectories = "0.7"
PiccoloQuantumObjects = "0.8"
Random = "1.10, 1.11, 1.12"
Reexport = "1.2"
SparseArrays = "1.10, 1.11, 1.12"
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/ipopt_callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ T_max = 1.0
u_bounds = [(-1.0, 1.0), (-1.0, 1.0)]
T = 50
Δt = 0.2
sys = QuantumSystem(0.1 * GATES[:Z], [GATES[:X], GATES[:Y]], T_max, u_bounds)
sys = QuantumSystem(0.1 * GATES[:Z], [GATES[:X], GATES[:Y]], u_bounds)
ψ_init = Vector{ComplexF64}([1.0, 0.0])
ψ_target = Vector{ComplexF64}([0.0, 1.0])

Expand Down Expand Up @@ -70,7 +70,7 @@ end
# Using a callback to get the best trajectory from all the optimization iterations
T_max = 1.0
u_bounds = [(-1.0, 1.0), (-1.0, 1.0)]
sys2 = QuantumSystem(0.15 * GATES[:Z], [GATES[:X], GATES[:Y]], T_max, u_bounds)
sys2 = QuantumSystem(0.15 * GATES[:Z], [GATES[:X], GATES[:Y]], u_bounds)
ψ_init2 = Vector{ComplexF64}([0.0, 1.0])
ψ_target2 = Vector{ComplexF64}([1.0, 0.0])

Expand Down
Loading
Loading