Skip to content

Commit

Permalink
Cudaq <> Superstaq integration (#2423)
Browse files Browse the repository at this point in the history
* poc infleqtion server files

Signed-off-by: Bharath <[email protected]>

* c++ existing tests links for server

Signed-off-by: Bharath <[email protected]>

* add new directory

Signed-off-by: Bharath <[email protected]>

* some debug prints in c++ tests

Signed-off-by: Bharath <[email protected]>

* draft mock qpu sketch

Signed-off-by: Bharath <[email protected]>

* add license header

Signed-off-by: Bharath <[email protected]>

* Add infleqtion python test with mockserver

* Ready to built testing wheel

* Revert testIonQ

* More reversions

* DCO Remediation Commit for vtomole <[email protected]>

I, vtomole <[email protected]>, hereby add my Signed-off-by to this commit: bc10bec
I, vtomole <[email protected]>, hereby add my Signed-off-by to this commit: 6f444dd
I, vtomole <[email protected]>, hereby add my Signed-off-by to this commit: 64463c1
I, vtomole <[email protected]>, hereby add my Signed-off-by to this commit: ad36074

Signed-off-by: vtomole <[email protected]>

* Run clang formatter

Signed-off-by: vtomole <[email protected]>

* Format with yapf

Signed-off-by: vtomole <[email protected]>

* Run yapf with Google style

Signed-off-by: vtomole <[email protected]>

* add newline at end of some new files

Signed-off-by: Bharath <[email protected]>

* remove debug bell test

Signed-off-by: Bharath <[email protected]>

* Update infleqtion.yml

Signed-off-by: vtomole <[email protected]>

* Fix a typo in cmake
* Use unused port '62447'
* Add the new sub-directory to cmake

Signed-off-by: Pradnya Khalate <[email protected]>

* some review responses + updates

Signed-off-by: Bharath <[email protected]>

* fix: commit format

Signed-off-by: Bharath <[email protected]>

* Test for all gates, modifiers
* Check observe call
* Skip the `observe` tests on C++ since the mock server returns hard-coded values
* Python `observe` test works but the expectation value may be out-of-range due to low number of shots
* `cu3` is not (yet) supported
* Updated C++ tests
* Add state prep pass in lowering pipeline
* Fix symbolic links

Signed-off-by: Pradnya Khalate <[email protected]>

* update backend name

Signed-off-by: Bharath <[email protected]>

* remove unused shots assignment

Signed-off-by: Bharath <[email protected]>

* override polling seconds and error for canceled job

Signed-off-by: Bharath <[email protected]>

* Additional tests for multiple qvectors and multiple measurements

Signed-off-by: Pradnya Khalate <[email protected]>

---------

Signed-off-by: Bharath <[email protected]>
Signed-off-by: vtomole <[email protected]>
Signed-off-by: Pradnya Khalate <[email protected]>
Co-authored-by: Bharath <[email protected]>
Co-authored-by: Bharath Thotakura <[email protected]>
Co-authored-by: Pradnya Khalate <[email protected]>
  • Loading branch information
4 people authored Dec 10, 2024
1 parent 917146d commit d87720e
Show file tree
Hide file tree
Showing 53 changed files with 884 additions and 16 deletions.
1 change: 1 addition & 0 deletions lib/Optimizer/CodeGen/TranslateToOpenQASM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static LogicalResult translateOperatorName(quake::OperatorInterface optor,
.Case("ry", "cry")
.Case("rz", "crz")
.Case("swap", "cswap")
.Case("u3", "cu3")
.Default(qkeName);
} else if (optor.getControls().size() == 2) {
name = StringSwitch<StringRef>(qkeName).Case("x", "ccx").Default("");
Expand Down
35 changes: 35 additions & 0 deletions lib/Optimizer/Transforms/DecompositionPatterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,40 @@ struct R1ToU3 : public OpRewritePattern<quake::R1Op> {
}
};

// quake.r1<adj> (θ) target
// ─────────────────────────────────
// quake.r1(-θ) target
struct R1AdjToR1 : public OpRewritePattern<quake::R1Op> {
using OpRewritePattern<quake::R1Op>::OpRewritePattern;

void initialize() { setDebugName("R1AdjToR1"); }

LogicalResult matchAndRewrite(quake::R1Op op,
PatternRewriter &rewriter) const override {
if (!op.getControls().empty())
return failure();
if (!op.isAdj())
return failure();

// Op info
Location loc = op->getLoc();
Value target = op.getTarget();
Value angle = op.getParameter();
angle = rewriter.create<arith::NegFOp>(loc, angle);

// Necessary/Helpful constants
SmallVector<Value> noControls;
SmallVector<Value> parameters = {angle};

QuakeOperatorCreator qRewriter(rewriter);
qRewriter.create<quake::R1Op>(loc, parameters, noControls, target);

qRewriter.selectWiresAndReplaceUses(op, target);
rewriter.eraseOp(op);
return success();
}
};

// quake.swap a, b
// ───────────────────────────────────
// quake.cnot b, a;
Expand Down Expand Up @@ -1575,6 +1609,7 @@ void cudaq::populateWithAllDecompositionPatterns(RewritePatternSet &patterns) {
R1ToPhasedRx,
R1ToRz,
R1ToU3,
R1AdjToR1,
// RxOp patterns
CRxToCX,
RxToPhasedRx,
Expand Down
159 changes: 159 additions & 0 deletions python/tests/backends/test_Infleqtion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# ============================================================================ #
# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

import cudaq, pytest, os
from cudaq import spin
import numpy as np

## NOTE: Comment the following line which skips these tests in order to run in
# local dev environment after setting the API key
## NOTE: Superstaq costs apply
pytestmark = pytest.mark.skip("Infleqtion / Superstaq API key required")


@pytest.fixture(scope="session", autouse=True)
def do_something():
cudaq.set_target("infleqtion")
yield "Running the tests."
cudaq.__clearKernelRegistries()
cudaq.reset_target()


def assert_close(got) -> bool:
return got < -1.5 and got > -1.9


def test_simple_kernel():

@cudaq.kernel
def bell():
qubits = cudaq.qvector(2)
h(qubits[0])
x.ctrl(qubits[0], qubits[1])
mz(qubits)

counts = cudaq.sample(bell)
assert len(counts) == 2
assert "00" in counts
assert "11" in counts


def test_all_gates():

@cudaq.kernel
def all_gates():
q = cudaq.qubit()
h(q)
x(q)
y(q)
z(q)
r1(np.pi, q)
rx(np.pi, q)
ry(np.pi, q)
rz(np.pi, q)
s(q)
t(q)
u3(0.0, np.pi / 2, np.pi, q)
mz(q)

qvec = cudaq.qvector(2)
x(qvec[0])
swap(qvec[0], qvec[1])
mz(qvec)

## control modifiers
qubits = cudaq.qvector(2)
h.ctrl(qubits[0], qubits[1])
x.ctrl(qubits[1], qubits[0])
y.ctrl(qubits[0], qubits[1])
z.ctrl(qubits[1], qubits[0])
r1.ctrl(np.pi / 2, qubits[0], qubits[1])
rx.ctrl(np.pi / 4, qubits[1], qubits[0])
ry.ctrl(np.pi / 8, qubits[0], qubits[1])
rz.ctrl(np.pi, qubits[1], qubits[0])
s.ctrl(qubits[0], qubits[1])
t.ctrl(qubits[1], qubits[0])
# u3.ctrl(0.0, np.pi / 2, np.pi, qubits[0], qubits[1])
mz(qubits)

qreg = cudaq.qvector(3)
x(qreg[0])
x(qreg[1])
swap.ctrl(qreg[0], qreg[1], qreg[2])
mz(qreg)

## adjoint modifiers
r = cudaq.qubit()
r1.adj(np.pi, r)
rx.adj(np.pi / 2, r)
ry.adj(np.pi / 4, r)
rz.adj(np.pi / 8, r)
s.adj(r)
t.adj(r)
mz(r)

# Test here is that this runs
cudaq.sample(all_gates).dump()


def test_multiple_qvector():

@cudaq.kernel
def kernel():
qubits = cudaq.qvector(2)
ancilla = cudaq.qvector(2)
x(qubits)
h(ancilla)
mz(ancilla)

# Test here is that this runs
cudaq.sample(kernel).dump()


def test_multiple_measure():

@cudaq.kernel
def kernel():
q = cudaq.qvector(4)
a = cudaq.qvector(2)
h(q[0])
cx(q[0], q[1])
h(a)
cx(q[1], a[0])
mz(q[1])
mz(q[0])
mz(a)

# Test here is that this runs
cudaq.sample(kernel).dump()


def test_observe():
cudaq.set_random_seed(13)

@cudaq.kernel
def ansatz(theta: float):
qreg = cudaq.qvector(2)
x(qreg[0])
ry(theta, qreg[1])
x.ctrl(qreg[1], qreg[0])

# Define its spin Hamiltonian.
hamiltonian = 5.907 - 2.1433 * spin.x(0) * spin.x(1) - 2.1433 * spin.y(
0) * spin.y(1) + .21829 * spin.z(0) - 6.125 * spin.z(1)

res = cudaq.observe(ansatz, hamiltonian, .59, shots_count=2048)
## Need to adjust expectation value range
# assert assert_close(res.expectation())
print(res.expectation())


# leave for gdb debugging
if __name__ == "__main__":
loc = os.path.abspath(__file__)
pytest.main([loc, "-s"])
5 changes: 3 additions & 2 deletions runtime/cudaq/platform/default/rest/helpers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #
add_subdirectory(anyon)
add_subdirectory(oqc)
add_subdirectory(infleqtion)
add_subdirectory(ionq)
add_subdirectory(quantinuum)
add_subdirectory(iqm)
add_subdirectory(oqc)
add_subdirectory(quantinuum)
if (AWSSDK_ROOT)
add_subdirectory(braket)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# ============================================================================ #
# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #
target_sources(cudaq-rest-qpu PRIVATE InfleqtionServerHelper.cpp)
add_target_config(infleqtion)

add_library(cudaq-serverhelper-infleqtion SHARED InfleqtionServerHelper.cpp )
target_link_libraries(cudaq-serverhelper-infleqtion
PUBLIC
cudaq-common
fmt::fmt-header-only
)
install(TARGETS cudaq-serverhelper-infleqtion DESTINATION lib)
Loading

0 comments on commit d87720e

Please sign in to comment.