Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Place coding examples with legacy-like structure #19

Merged
merged 33 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3551372
add expressions and IR
kaosmicadei Jul 22, 2024
52c298e
update IR and Expressions
kaosmicadei Jul 22, 2024
68347c1
Merge branch 'main' into km/ir-plus-expressions
kaosmicadei Jul 22, 2024
fd5351a
update ir and expressions
kaosmicadei Jul 23, 2024
70a0735
update expression
kaosmicadei Jul 23, 2024
99269c9
add platforms
kaosmicadei Jul 23, 2024
63357e3
add examples
Doomsk Sep 13, 2024
755b3fa
add examples
Doomsk Sep 13, 2024
67250bb
add git submodule command on readme
Doomsk Sep 13, 2024
6f05103
add minor project changes
Doomsk Sep 30, 2024
0ed63b2
Merge branch 'main' into em/add_example
Doomsk Oct 8, 2024
9b660bb
improve README
Doomsk Oct 8, 2024
ee84244
add first docs pages
Doomsk Oct 8, 2024
f9b431a
add small version fixes
Doomsk Oct 16, 2024
193787e
add qadence legacy code
Doomsk Oct 16, 2024
7194518
fix parametric value
Doomsk Oct 24, 2024
c2877b3
fix parametric value
Doomsk Oct 24, 2024
e7c2fbb
small fixes
Doomsk Oct 25, 2024
4474a7d
lint
Doomsk Oct 25, 2024
bc3365f
lint
Doomsk Oct 25, 2024
fd9bef5
improve code prototype examples
Doomsk Oct 29, 2024
bb0a7d1
improve and fix code for code prototypes examples
Doomsk Nov 1, 2024
e9bf8f6
fix examples
Doomsk Nov 4, 2024
b50ad7f
add independent tests code prototypes
Doomsk Nov 14, 2024
186742e
fix pre-commit
Doomsk Nov 14, 2024
a76ab19
Merge branch 'refs/heads/main' into em/run_examples
Doomsk Nov 14, 2024
eb857ce
fix examples
Doomsk Dec 6, 2024
e83fe44
improve tests
Doomsk Dec 9, 2024
8ac6842
fix code for ruff
Doomsk Dec 10, 2024
caa13c7
fix analog & fresnel1 puzzles
Doomsk Dec 13, 2024
18bff9b
Add code prototypes for puzzles.
RolandMacDoland Dec 20, 2024
cff2cce
add code prototype examples in the test
Doomsk Jan 13, 2025
ccf2b23
Merge branch 'main' into em/run_examples
Doomsk Jan 13, 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
318 changes: 318 additions & 0 deletions examples/code_prototype.ipynb

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions examples/pulser_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

import numpy as np
from qadence2_expressions import RX, RY, add_qpu_directives, compile_to_model, parameter
from qadence2_platforms import OnEnum
from qadence2_platforms.compiler import compile_to_backend

a = parameter("a")
expr = RX(1.57 * a)(0) * RY(0.707 * a**2)(0)
print(f"expression: {str(expr)}")
if __name__ == "__main__":
a = parameter("a")
expr = RX(1.57 * a)(0) * RY(0.707 * a**2)(0)
print(f"expression: {str(expr)}")

add_qpu_directives({"digital": True})
model = compile_to_model(expr)
print(f"model: {model}\n")
add_qpu_directives({"digital": True})
model = compile_to_model(expr)
print(f"model: {model}\n")

f_params = {"a": np.array([1.0])}
compiled_model = compile_to_backend(model, "fresnel1")
res = compiled_model.sample(values=f_params, shots=10_000, on="emulator")
print(f"sample result: {res}")
f_params = {"a": np.array([1.0])}
compiled_model = compile_to_backend(model, "fresnel1")
res = compiled_model.sample(values=f_params, shots=10_000, on=OnEnum.EMULATOR)
print(f"sample result: {res}")
29 changes: 15 additions & 14 deletions examples/pyq_compiler.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from __future__ import annotations

import pyqtorch as pyq
import torch
from qadence2_expressions import RX, RY, add_qpu_directives, compile_to_model, parameter
from qadence2_platforms import OnEnum
from qadence2_platforms.compiler import compile_to_backend

a = parameter("a")
expr = RX(1.57 * a)(0) * RY(0.707 * a**2)(0)
print(f"expression: {str(expr)}")
if __name__ == "__main__":
a = parameter("a")
expr = RX(1.57 * a)(0) * RY(0.707 * a**2)(0)
print(f"expression: {str(expr)}")

add_qpu_directives({"digital": True})
model = compile_to_model(expr)
print(f"model: {model}\n")
add_qpu_directives({"digital": True})
model = compile_to_model(expr)
print(f"model: {model}\n")

f_params = {"a": torch.tensor(1.0, requires_grad=True)}
compiled_model = compile_to_backend(model, "pyqtorch")
res = compiled_model.sample(values=f_params, shots=10_000)
print(f"sample result: {res}")
f_params = {"a": torch.tensor(1.0, requires_grad=True)}
compiled_model = compile_to_backend(model, "pyqtorch")
res = compiled_model.sample(values=f_params, shots=10_000, on=OnEnum.EMULATOR)
print(f"sample result: {res}")

wf = compiled_model.run(state=pyq.zero_state(2), values=f_params)
dfdx = torch.autograd.grad(wf, f_params["a"], torch.ones_like(wf))[0]
print(f"{dfdx = }\n")
wf = compiled_model.run(values=f_params)
dfdx = torch.autograd.grad(wf, f_params["a"], torch.ones_like(wf))[0]
print(f"{dfdx = }\n")
15 changes: 6 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ classifiers = [
# always specify a version for each package
# to maintain consistency
dependencies = [
"qadence2-expressions~=0.3.0",
"qadence2-ir~=0.2.0",
"qadence2_platforms~=0.2.0",
"qadence2-expressions",
"qadence2-ir",
"qadence2_platforms",
"pyqtorch",
]

[tool.hatch.metadata]
Expand All @@ -51,6 +52,7 @@ Source = "https://github.com/pasqal-io/qadence2-core"
[tool.hatch.envs.default]
features = ["extras"]
dependencies = [
"hypothesis",
"pytest",
"pytest-cov",
"pytest-xdist",
Expand Down Expand Up @@ -108,6 +110,7 @@ exclude = [
"/tests",
"/docs",
"/examples",
"/code_prototypes",
]

[tool.hatch.build.targets.wheel]
Expand All @@ -116,12 +119,6 @@ packages = ["qadence2"]
[tool.coverage.run]
branch = true
parallel = true
# uncomment to omit any file from the
# coverage. Regexps can be used
# to select all files from a folder
#omit = [
# "template_python/to_omit.py",
#]

[tool.coverage.report]
exclude_lines = [
Expand Down
10 changes: 10 additions & 0 deletions qadence2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from __future__ import annotations

from .compiler import Directives, Register, Settings, code_compile

__all__ = [
"code_compile",
"Register",
"Directives",
"Settings",
]
111 changes: 111 additions & 0 deletions qadence2/compiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Literal, Union

from qadence2_expressions import (
add_grid_options,
add_qpu_directives,
compile_to_model,
reset_ir_options,
set_grid_scale,
set_grid_type,
set_number_qubits,
set_qubits_positions,
)
from qadence2_platforms import AbstractInterface
from qadence2_platforms.compiler import compile_to_backend


def code_compile(
expr: Any,
backend_name: str,
register: Register | dict | None = None,
directives: Directives | dict | None = None,
settings: Settings | dict | None = None,
**kwargs: Any,
) -> AbstractInterface:
set_config_compiler(register, directives, settings)
model = compile_to_model(expr)
reset_ir_options()
return compile_to_backend(model, backend_name)


@dataclass
class Register:
"""
Register class to handle register related data. It can be used instead
of pure dictionary to enforce some necessary arguments and validate them.

Args
* grid_type (`Literal["linear", "square", "triangular"]`)
* grid_scale (`float`). Default is `1.0`
* qubit_positions (`list[tuple[int, int]]`). Default is empty `list`
* number_qubits (`int` or `None`). Default is `None`
* grid_options (`dict`). Default is empty `dict`
"""

grid_type: Literal["linear", "square", "triangular"]
grid_scale: float = field(default=1.0)
qubit_positions: list = field(default_factory=list)
number_qubits: Union[int, None] = field(default=None)
grid_options: dict = field(default_factory=dict)

def add_configs(self) -> None:
set_grid_scale(self.grid_scale)
set_grid_type(self.grid_type)
if self.qubit_positions:
set_qubits_positions(self.qubit_positions)
else:
set_number_qubits(self.number_qubits)

if self.grid_options:
add_grid_options(self.grid_options)


class Directives(dict):
def add_configs(self) -> None:
add_qpu_directives(self)


class Settings(dict):
def add_configs(self) -> None:
add_qpu_directives(self)


def set_config_register(register: Register | dict) -> None:
"""
It is assumed to have all the values to pass to the IR register.

Args:
register: a Register class or a dict containing register data such as
grid type, grid scale, qubit positions, and additional configs.
"""
if not isinstance(register, Register):
register = Register(**register)
register.add_configs()


def set_config_directives(directives: Directives | dict) -> None:
if not isinstance(directives, Directives):
directives = Directives(**directives)
directives.add_configs()


def set_config_settings(settings: Settings | dict) -> None:
if not isinstance(settings, Settings):
settings = Settings(**settings)
settings.add_configs()


def set_config_compiler(
register: Register | dict | None = None,
directives: Directives | dict | None = None,
settings: Settings | dict | None = None,
) -> None:
if register:
set_config_register(register)
if directives:
set_config_directives(directives)
if settings:
set_config_settings(settings)
Empty file added qadence2/extensions/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions qadence2/extensions/legacy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from __future__ import annotations

from qadence2_expressions.operators import CZ, X, Y, Z

from .model import QuantumModel
from .operators import CNOT, RX, RY, RZ, N
from .utils import add, chain, kron, mul, pow

__all__ = [
"QuantumModel",
"add",
"mul",
"chain",
"kron",
"pow",
"RX",
"RY",
"RZ",
"CNOT",
"X",
"Y",
"Z",
"CZ",
"N",
]
11 changes: 11 additions & 0 deletions qadence2/extensions/legacy/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from __future__ import annotations

from typing import Any

from qadence2_platforms import AbstractInterface

from qadence2.compiler import code_compile


def QuantumModel(expr: Any, backend: str, **settings: Any) -> AbstractInterface:
return code_compile(expr, backend, **settings)
31 changes: 31 additions & 0 deletions qadence2/extensions/legacy/operators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from __future__ import annotations

import qadence2_expressions.operators as ops
from qadence2_expressions import variable
from qadence2_expressions.core.expression import Expression

# The N = (1/2)(I-Z) operator
N = ops.Z1


def CNOT(target: int, control: int) -> Expression:
return ops.NOT(target=(target,), control=(control,))


def RX(target: int, parameters: Expression | str | float) -> Expression:
return ops.RX(angle=_get_variable(parameters))(target)


def RY(target: int, parameters: Expression | str | float) -> Expression:
return ops.RY(angle=_get_variable(parameters))(target)


def RZ(target: int, parameters: Expression | str | float) -> Expression:
return ops.RZ(angle=_get_variable(parameters))(target)


def _get_variable(expr: Expression | str | float) -> Expression:
if isinstance(expr, str):
return variable(expr)
if isinstance(expr, (Expression, float)):
return expr
34 changes: 34 additions & 0 deletions qadence2/extensions/legacy/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from __future__ import annotations

from enum import Enum, auto
from typing import Generator

from qadence2_expressions.core.expression import Expression


class ParadigmStrategy(Enum):
DIGITAL = auto()
ANALOG = auto()
SDAQC = auto()
BDAQC = auto()
RYDBERG = auto()


def add(expr: Generator | list[Expression]) -> Expression:
return Expression.add(*tuple(expr))


def mul(expr: Generator | list[Expression]) -> Expression:
return Expression.mul(*tuple(expr))


def chain(expr: Generator | list[Expression]) -> Expression:
return mul(expr)


def kron(expr: Generator | list[Expression]) -> Expression:
return Expression.kron(*tuple(expr))


def pow(expr: Generator | list[Expression]) -> Expression:
return Expression.pow(*tuple(expr))
15 changes: 0 additions & 15 deletions qadence2/main.py

This file was deleted.

1 change: 1 addition & 0 deletions qadence2/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from __future__ import annotations
21 changes: 21 additions & 0 deletions tests/code_prototypes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from __future__ import annotations

from .implementation import (
pulser_basic_mis_pulse_v1,
pulser_basic_ramp_v2,
pulser_basic_rx_v1,
pyq_basic_diff_v1,
pyq_basic_rx_v1,
pyq_basic_training_v1,
pyq_basic_training_v2,
)

__all__ = [
"pulser_basic_rx_v1",
"pyq_basic_diff_v1",
"pyq_basic_training_v2",
"pyq_basic_training_v1",
"pyq_basic_rx_v1",
"pulser_basic_ramp_v2",
"pulser_basic_mis_pulse_v1",
]
Loading
Loading