Skip to content

Commit

Permalink
Update Emulator interface. (#943)
Browse files Browse the repository at this point in the history
* refactor `AnalogGate` interface to accept and return `StateVector` objects. fixing tests.

* adding `tocsr` to Hamiltonian.

* adding API to `HamiltonianData`.

* adding doc strings.

* switching to list as hamiltonian output.

* rename class.

* adding fock state API.

* adding fock state API.

* removing print.

* adding tests.

* adding more tests.

* removing unused code.

* expanding tests.

* rename file.

* fixing bug in `_apply`.

* updating tests.
  • Loading branch information
weinbe58 committed May 29, 2024
1 parent 98e2d0f commit 0317977
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 100 deletions.
16 changes: 15 additions & 1 deletion pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ dev = [
"scikit-optimize>=0.9.0",
"matplotlib>=3.8.1",
"icecream>=2.1.3",
"tqdm>=4.66.4",
]

[tool.pdm.scripts]
Expand Down
32 changes: 26 additions & 6 deletions src/bloqade/emulate/ir/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,35 @@ def __post_init__(self):
def __len__(self):
return len(self.sites)

def same(self, other: Any) -> bool:
if not isinstance(other, Register):
return False

return (
self.atom_type == other.atom_type
and self.blockade_radius == other.blockade_radius
and set(self.sites) == set(other.sites)
)

# for hashing/comparing I only want to compare based on the effective
# fock space that gets generated which is determined by the geometry
# only if the blockade radius is non-zero. I overload the __eq__ and
# __hash__ methods to achieve this.

def __eq__(self, other: Any):
if isinstance(other, Register):
return (
self.atom_type == other.atom_type
and self.blockade_radius == other.blockade_radius
and set(self.sites) == set(other.sites)
if not isinstance(other, Register):
return False

if self.blockade_radius == Decimal("0") and other.blockade_radius == Decimal(
"0"
):
# if blockade radius is zero, then the positions are irrelevant
# because the fock states generated by the geometry are the same
return self.atom_type == other.atom_type and len(self.sites) == len(
other.sites
)

return False
return self.same(other)

def __hash__(self) -> int:
if self.blockade_radius == Decimal("0"):
Expand Down
15 changes: 12 additions & 3 deletions src/bloqade/emulate/ir/space.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from dataclasses import dataclass
from numpy.typing import NDArray
from beartype.typing import TYPE_CHECKING
from beartype.typing import TYPE_CHECKING, Any
import numpy as np
from enum import Enum

if TYPE_CHECKING:
from .emulator import Register
from .atom_type import AtomType
from .state_vector import StateVector

MAX_PRINT_SIZE = 30

Expand All @@ -28,6 +29,12 @@ def __post_init__(self):

assert isinstance(self.program_register, Register)

def __eq__(self, other: Any) -> bool:
if not isinstance(other, Space):
return False

return self.program_register == other.program_register

@classmethod
def create(cls, register: "Register"):
sites = register.sites
Expand Down Expand Up @@ -193,10 +200,12 @@ def index_to_fock_state(self, index: int) -> str:
self.configurations[index], self.n_atoms
)

def zero_state(self, dtype=np.float64) -> NDArray:
def zero_state(self, dtype=np.float64) -> "StateVector":
from .state_vector import StateVector

state = np.zeros(self.size, dtype=dtype)
state[0] = 1.0
return state
return StateVector(state, self)

def sample_state_vector(
self, state_vector: NDArray, n_samples: int, project_hyperfine: bool = True
Expand Down
Loading

0 comments on commit 0317977

Please sign in to comment.