Skip to content
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
63a3271
renaming
bettinaheim Apr 1, 2025
879af99
bindings for handler specific operators
bettinaheim Apr 1, 2025
2692e96
more bindings
bettinaheim Apr 2, 2025
42fe0a3
bindings for product_op
bettinaheim Apr 2, 2025
31b57bd
handler bindings
bettinaheim Apr 2, 2025
859e933
test setup
bettinaheim Apr 2, 2025
6163533
more tests
bettinaheim Apr 3, 2025
80d1cbe
more tests
bettinaheim Apr 8, 2025
259a849
covering the basic arithmetics
bettinaheim Apr 8, 2025
5edab51
renaming/moving existing spin ops tests
bettinaheim Apr 8, 2025
1692bd0
tests for boson and fermion operator bindings
bettinaheim Apr 8, 2025
52ab6f5
operator conversions
bettinaheim Apr 9, 2025
1c4dc18
spin op bindings update part 1
bettinaheim Apr 9, 2025
fe9c8d4
spin op bindings update part 2
bettinaheim Apr 9, 2025
57ce688
merge old and new spin ops tests
bettinaheim Apr 9, 2025
23e6bd4
forgot to add plus and minus
bettinaheim Apr 9, 2025
77b6b53
enabling the scipy test
bettinaheim Apr 9, 2025
8290134
making sure all operator tests pass before modifying the python opera…
bettinaheim Apr 9, 2025
8592e29
parameter descriptions in c++
bettinaheim Apr 10, 2025
eb93c6a
scalar operators part 1
bettinaheim Apr 11, 2025
6da34a9
dealing better with constant scalar
bettinaheim Apr 11, 2025
2b77e15
properties
bettinaheim Apr 11, 2025
1513c9f
some prep for supporting custom matrix operators in Python
bettinaheim Apr 11, 2025
fd9cbfd
support for defining custom matrix operators
bettinaheim Apr 14, 2025
2f2ca96
[WIP] commenting out the old infrastructure
bettinaheim Apr 14, 2025
2831592
draft to keep _evaluate
bettinaheim Apr 15, 2025
94c6944
getting closer to having the tests pass again
bettinaheim Apr 15, 2025
f381aa2
python tests largely are back to passing
bettinaheim Apr 15, 2025
406b2dd
proper tests for custom operators
bettinaheim Apr 16, 2025
1aa5dcd
python tests for commutation relations
bettinaheim Apr 16, 2025
cd37e5a
finished with the tests
bettinaheim Apr 16, 2025
998f02e
simplifying scalar op
bettinaheim Apr 16, 2025
1f2439f
unifying the scalar ops classes
bettinaheim Apr 16, 2025
89d0e23
removing commented out code
bettinaheim Apr 16, 2025
1a3c253
adding missing overloads
bettinaheim Apr 24, 2025
10c5541
minor fix
bettinaheim Apr 24, 2025
ce37b39
spin module name
bettinaheim Apr 24, 2025
6611462
splitting out separate operator and dynamics module
bettinaheim Apr 24, 2025
e4a27b2
cleaning up directory structure - some breaking changes
bettinaheim Apr 25, 2025
c321b66
cleaning up class names - more breaking changes
bettinaheim Apr 25, 2025
b7dbfc5
more clean up
bettinaheim Apr 25, 2025
ff16339
more clean up
bettinaheim Apr 25, 2025
9ba730b
just some comments
bettinaheim Apr 25, 2025
6c1a08d
forgot to save a file
bettinaheim Apr 25, 2025
f82b328
getting updates from main
bettinaheim Apr 28, 2025
59dcbce
cleaning up notes and comments in py_spin_op.cpp
bettinaheim Apr 28, 2025
f6ad246
cleaning up evaluate
bettinaheim Apr 28, 2025
f25fa56
checking parameters after evaluation
bettinaheim Apr 28, 2025
7c6e43a
formatting and spell check
bettinaheim Apr 28, 2025
c69faac
more formatting
bettinaheim Apr 28, 2025
f97e7bc
undoing change to teh build script
bettinaheim Apr 28, 2025
a0aba12
fixing build errors
bettinaheim Apr 29, 2025
0230fea
addressing some review comments
bettinaheim Apr 29, 2025
14de292
factoring out helpers
bettinaheim Apr 29, 2025
c9a74c5
code formatting
bettinaheim Apr 29, 2025
759b850
Merge branch 'main' into python_ops
bettinaheim Apr 29, 2025
e083d54
more formatting
bettinaheim Apr 29, 2025
84cf3df
Merge branch 'python_ops' of https://github.com/bettinaheim/cuda-quan…
bettinaheim Apr 29, 2025
4b21de0
examples
bettinaheim Apr 29, 2025
5961eda
comments
bettinaheim Apr 29, 2025
35402d5
getting updates from main
bettinaheim Apr 29, 2025
f19c72f
formatting
bettinaheim Apr 29, 2025
f5bf9d1
formatting
bettinaheim Apr 29, 2025
c2f68b3
SupportsComplex does not seem to work the way it was intended
bettinaheim Apr 30, 2025
f4adc0d
a stab at cleaning up the docs
bettinaheim Apr 30, 2025
782c6dc
Merge branch 'main' into python_ops
bettinaheim Apr 30, 2025
558ae73
forgot to commit a file
bettinaheim Apr 30, 2025
527f96e
Merge branch 'python_ops' of https://github.com/bettinaheim/cuda-quan…
bettinaheim Apr 30, 2025
96173af
C++ formatting
bettinaheim Apr 30, 2025
0fc30f3
python formatting
bettinaheim Apr 30, 2025
79ae0ef
undoing script changes
bettinaheim Apr 30, 2025
c741899
serialization for product
bettinaheim Apr 30, 2025
7c1b808
cpp formatting
bettinaheim Apr 30, 2025
a097265
python formatting
bettinaheim Apr 30, 2025
df0ebec
fixing test
bettinaheim Apr 30, 2025
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
32 changes: 16 additions & 16 deletions docs/sphinx/examples/python/dynamics/cavity_qed.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, Schedule, ScipyZvodeIntegrator
from cudaq import boson, Schedule, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand All @@ -15,17 +15,17 @@

# Alias for commonly used operators
# Cavity operators
a = operators.annihilate(1)
a_dag = operators.create(1)
a = boson.annihilate(1)
a_dag = boson.create(1)

# Atom operators
sm = operators.annihilate(0)
sm_dag = operators.create(0)
sm = boson.annihilate(0)
sm_dag = boson.create(0)

# Defining the Hamiltonian for the system: self-energy terms and cavity-atom interaction term.
# This is the so-called Jaynes-Cummings model:
# https://en.wikipedia.org/wiki/Jaynes%E2%80%93Cummings_model
hamiltonian = 2 * np.pi * operators.number(1) + 2 * np.pi * operators.number(
hamiltonian = 2 * np.pi * boson.number(1) + 2 * np.pi * boson.number(
0) + 2 * np.pi * 0.25 * (sm * a_dag + sm_dag * a)

# Initial state of the system
Expand All @@ -41,23 +41,23 @@
schedule = Schedule(steps, ["time"])

# First, evolve the system without any collapse operators (ideal).
evolution_result = cudaq.evolve(
hamiltonian,
dimensions,
schedule,
rho0,
observables=[operators.number(1), operators.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
evolution_result = cudaq.evolve(hamiltonian,
dimensions,
schedule,
rho0,
observables=[boson.number(1),
boson.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())

# Then, evolve the system with a collapse operator modeling cavity decay (leaking photons)
evolution_result_decay = cudaq.evolve(
hamiltonian,
dimensions,
schedule,
rho0,
observables=[operators.number(1), operators.number(0)],
observables=[boson.number(1), boson.number(0)],
collapse_operators=[np.sqrt(0.1) * a],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
Expand Down
14 changes: 7 additions & 7 deletions docs/sphinx/examples/python/dynamics/gate_calibration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, Schedule, ScalarOperator, ScipyZvodeIntegrator
from cudaq import boson, Schedule, ScalarOperator, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand Down Expand Up @@ -55,16 +55,16 @@ def cost_function(amps):
amplitude = 100 * amps[0]
drag_amp = 100 * amps[1]
# Qubit Hamiltonian
hamiltonian = detuning * operators.number(0) + (
anharmonicity / 2) * operators.create(0) * operators.create(
0) * operators.annihilate(0) * operators.annihilate(0)
hamiltonian = detuning * boson.number(0) + (
anharmonicity / 2) * boson.create(0) * boson.create(
0) * boson.annihilate(0) * boson.annihilate(0)
# Drive term
hamiltonian += amplitude * ScalarOperator(gaussian) * (
operators.create(0) + operators.annihilate(0))
hamiltonian += amplitude * ScalarOperator(gaussian) * (boson.create(0) +
boson.annihilate(0))

# Drag term (leakage reduction)
hamiltonian += 1j * drag_amp * ScalarOperator(dgaussian) * (
operators.annihilate(0) - operators.create(0))
boson.annihilate(0) - boson.create(0))

# We optimize for a X(pi/2) rotation
evolution_result = cudaq.evolve(hamiltonian,
Expand Down
6 changes: 3 additions & 3 deletions docs/sphinx/examples/python/dynamics/heisenberg_model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, spin, Schedule, ScipyZvodeIntegrator
from cudaq import spin, Schedule, ScipyZvodeIntegrator

import numpy as np
import cupy as cp
Expand All @@ -25,7 +25,7 @@
spin_state += str(int(i % 2))

# Observable is the staggered magnetization operator
staggered_magnetization_op = operators.zero()
staggered_magnetization_op = spin.empty()
for i in range(N):
if i % 2 == 0:
staggered_magnetization_op += spin.z(i)
Expand All @@ -42,7 +42,7 @@
Jz = g

# Construct the Hamiltonian
H = operators.zero()
H = spin.empty()

for i in range(N - 1):
H += Jx * spin.x(i) * spin.x(i + 1)
Expand Down
8 changes: 4 additions & 4 deletions docs/sphinx/examples/python/dynamics/landau_zener.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import spin, operators, ScalarOperator, Schedule, ScipyZvodeIntegrator
from cudaq import spin, boson, ScalarOperator, Schedule, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand All @@ -20,8 +20,8 @@
# Define some shorthand operators
sx = spin.x(0)
sz = spin.z(0)
sm = operators.annihilate(0)
sm_dag = operators.create(0)
sm = boson.annihilate(0)
sm_dag = boson.create(0)

# Dimensions of sub-system. We only have a single degree of freedom of dimension 2 (two-level system).
dimensions = {0: 2}
Expand Down Expand Up @@ -51,7 +51,7 @@
dimensions,
schedule,
psi0,
observables=[operators.number(0)],
observables=[boson.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
Expand Down
10 changes: 5 additions & 5 deletions docs/sphinx/examples/python/dynamics/mgmn/initial_state.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, spin, Schedule, RungeKuttaIntegrator
from cudaq import spin, Schedule, RungeKuttaIntegrator

import numpy as np
import matplotlib.pyplot as plt
Expand All @@ -19,14 +19,14 @@
dimensions[i] = 2

# Observable is the average magnetization operator
avg_magnetization_op = operators.zero()
avg_magnetization_op = spin.empty()
for i in range(N):
avg_magnetization_op += (spin.z(i) / N)

# Arbitrary coupling constant
g = 1.0
# Construct the Hamiltonian
H = operators.zero()
H = spin.empty()
for i in range(N):
H += 2 * np.pi * spin.x(i)
H += 2 * np.pi * spin.y(i)
Expand All @@ -38,9 +38,9 @@
schedule = Schedule(steps, ["time"])

# Initial state (expressed as an enum)
psi0 = cudaq.operator.InitialState.ZERO
psi0 = cudaq.dynamics.InitialState.ZERO
# This can also be used to initialize a uniformly-distributed wave-function instead.
# `psi0 = cudaq.operator.InitialState.UNIFORM`
# `psi0 = cudaq.dynamics.InitialState.UNIFORM`

# Run the simulation
evolution_result = cudaq.evolve(H,
Expand Down
6 changes: 3 additions & 3 deletions docs/sphinx/examples/python/dynamics/mgmn/multi_gpu.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, spin, Schedule, RungeKuttaIntegrator
from cudaq import spin, Schedule, RungeKuttaIntegrator

import numpy as np
import cupy as cp
Expand Down Expand Up @@ -29,7 +29,7 @@
spin_state += str(int(i % 2))

# Observable is the staggered magnetization operator
staggered_magnetization_op = operators.zero()
staggered_magnetization_op = spin.empty()
for i in range(N):
if i % 2 == 0:
staggered_magnetization_op += spin.z(i)
Expand All @@ -46,7 +46,7 @@
Jz = g

# Construct the Hamiltonian
H = operators.zero()
H = spin.empty()

for i in range(N - 1):
H += Jx * spin.x(i) * spin.x(i + 1)
Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/examples/python/dynamics/pulse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import spin, operators, ScalarOperator, Schedule, ScipyZvodeIntegrator
from cudaq import spin, boson, ScalarOperator, Schedule, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand Down Expand Up @@ -59,7 +59,7 @@ def signal(t):
dimensions,
schedule,
psi0,
observables=[operators.number(0)],
observables=[boson.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/examples/python/dynamics/silicon_spin_qubit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import spin, operators, Schedule, ScalarOperator, ScipyZvodeIntegrator
from cudaq import spin, boson, Schedule, ScalarOperator, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand Down Expand Up @@ -36,7 +36,7 @@
dimensions,
schedule,
rho0,
observables=[operators.number(0)],
observables=[boson.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
Expand Down
8 changes: 4 additions & 4 deletions docs/sphinx/examples/python/dynamics/tensor_callback.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import ElementaryOperator, spin, operators, Schedule, ScipyZvodeIntegrator
from cudaq import MatrixOperatorElement, operators, boson, Schedule, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand All @@ -26,10 +26,10 @@ def callback_tensor(t):
lz_formula_p1 = 1.0 - lz_formula_p0

# Let's define the control term as a callback tensor that acts on 2-level systems
ElementaryOperator.define("lz_op", [2], callback_tensor)
operators.define("lz_op", [2], callback_tensor)

# Hamiltonian
hamiltonian = ElementaryOperator("lz_op", [0])
hamiltonian = operators.instantiate("lz_op", [0])

# Dimensions of sub-system. We only have a single degree of freedom of dimension 2 (two-level system).
dimensions = {0: 2}
Expand All @@ -46,7 +46,7 @@ def callback_tensor(t):
dimensions,
schedule,
psi0,
observables=[operators.number(0)],
observables=[boson.number(0)],
collapse_operators=[],
store_intermediate_results=True,
integrator=ScipyZvodeIntegrator())
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/examples/python/dynamics/transmon_resonator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cudaq
from cudaq import operators, spin, Schedule, ScipyZvodeIntegrator
from cudaq import operators, spin, operators, Schedule, ScipyZvodeIntegrator
import numpy as np
import cupy as cp
import os
Expand Down
2 changes: 1 addition & 1 deletion python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,4 @@ if(CUDAQ_BUILD_TESTS)
endif()

add_subdirectory(runtime/interop)
add_subdirectory(cudaq/operator)
add_subdirectory(cudaq/dynamics)
20 changes: 10 additions & 10 deletions python/cudaq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,18 @@
qreg = cudaq_runtime.qvector

# Operator API
from .operator.definitions import spin, SpinOperator
# Re-export non-spin-op operators under the `operators` namespace
# e.g. `cudaq.operators.annihilate`
from .operator import operators as operators
# Operator types (in addition to `spin` types)
# e.g., allows users to use `cudaq.ScalarOperator(lambda...)`
from .operator import Operator, ElementaryOperator, ScalarOperator
from .operators import boson
from .operators import fermion
from .operators import spin
from .operators import custom as operators
from .operators.definitions import *
from .operators.manipulation import OperatorArithmetics
import cudaq.operators.expressions # needs to be imported, since otherwise e.g. evaluate is not defined

# Time evolution API
from .operator.schedule import Schedule
from .operator.evolution import evolve, evolve_async
from .operator.integrators import *
from .dynamics.schedule import Schedule
from .dynamics.evolution import evolve, evolve_async
from .dynamics.integrators import *

# Optimizers + Gradients
optimizers = cudaq_runtime.optimizers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,5 @@
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

from .definitions import operators, spin
from .evolution import evolve, evolve_async
from .expressions import Operator, OperatorSum, ProductOperator, ElementaryOperator, ScalarOperator, RydbergHamiltonian
from .helpers import NumericType, InitialState
from .schedule import Schedule
from .helpers import InitialState
from .schedule import Schedule
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import logging
import numpy
from numbers import Number
from typing import Any, Mapping, List, Sequence, Union

from .expressions import ElementaryOperator, ScalarOperator
from .manipulation import OperatorArithmetics
from typing import Any, Mapping, List, Union
from ..operators import ElementaryOperator, OperatorArithmetics, ScalarOperator
from .schedule import Schedule
import warnings

Expand Down Expand Up @@ -197,16 +195,17 @@ def evaluate(
self, op: ElementaryOperator | ScalarOperator
) -> CudmOperatorTerm | CallbackCoefficient | Number:
logger.info(f"Evaluating {op}")
if isinstance(op, ScalarOperator):
if op._constant_value is None:
if not hasattr(op, "degrees"):
if not op.is_constant():
return CPUCallback(
self._wrap_callback(op.generator, op.parameters))
self._wrap_callback(lambda **kwargs: op.evaluate(**kwargs),
op.parameters))
else:
return op._constant_value
return op.evaluate()
else:
if op._id == "identity":
if op == op.__class__(op.degrees[0]):
return 1.0
if len(op.parameters) > 0:
if hasattr(op, "parameters") and len(op.parameters) > 0:
for param in op.parameters:
if param not in self._schedule._parameters:
raise ValueError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

from .cudm_helpers import CuDensityMatOpConversion, constructLiouvillian
from .schedule import Schedule
from .expressions import Operator
from cudaq.mlir._mlir_libs._quakeDialects import cudaq_runtime
from ..operators import Operator
from ..mlir._mlir_libs._quakeDialects import cudaq_runtime
from .cudm_helpers import cudm, CudmStateType
from .cudm_state import CuDensityMatState, as_cudm_state
from .helpers import InitialState, InitialStateArgT
Expand Down Expand Up @@ -79,14 +79,14 @@ def evolve_dynamics(
# Always solve the master equation if the input is a density matrix
me_solve = True

with ScopeTimer("evolve.hamiltonian._evaluate") as timer:
ham_term = hamiltonian._evaluate(
with ScopeTimer("evolve.hamiltonian._transform") as timer:
ham_term = hamiltonian._transform(
CuDensityMatOpConversion(dimensions, schedule))
linblad_terms = []
for c_op in collapse_operators:
with ScopeTimer("evolve.collapse_operators._evaluate") as timer:
with ScopeTimer("evolve.collapse_operators._transform") as timer:
linblad_terms.append(
c_op._evaluate(CuDensityMatOpConversion(dimensions, schedule)))
c_op._transform(CuDensityMatOpConversion(dimensions, schedule)))

with ScopeTimer("evolve.constructLiouvillian") as timer:
liouvillian = constructLiouvillian(hilbert_space_dims, ham_term,
Expand All @@ -103,7 +103,7 @@ def evolve_dynamics(
expectation_op = [
cudm.Operator(
hilbert_space_dims,
(observable._evaluate(CuDensityMatOpConversion(dimensions)), 1.0))
(observable._transform(CuDensityMatOpConversion(dimensions)), 1.0))
for observable in observables
]
integrator.set_state(initial_state, schedule._steps[0])
Expand Down
File renamed without changes.
Loading
Loading