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

Use sparse simulator by default #187

Merged
merged 2 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 2 additions & 3 deletions unitary/alpha/quantum_effect_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
import cirq

import unitary.alpha as alpha
from unitary.alpha.sparse_vector_simulator import SparseSimulator

Q0 = cirq.NamedQubit("q0")
Q1 = cirq.NamedQubit("q1")


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_quantum_if(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("q0", 1)
Expand All @@ -46,7 +45,7 @@ def test_quantum_if(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_anti_control(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("q0", 0)
Expand Down
37 changes: 28 additions & 9 deletions unitary/alpha/quantum_object_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
import cirq

import unitary.alpha as alpha
from unitary.alpha.sparse_vector_simulator import SparseSimulator


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_negation(simulator, compile_to_qubits):
piece = alpha.QuantumObject("t", 0)
board = alpha.QuantumWorld(
Expand All @@ -38,7 +37,7 @@ def test_negation(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_add_world_after_state_change(simulator, compile_to_qubits):
piece = alpha.QuantumObject("t", 0)
piece += 1
Expand All @@ -48,10 +47,20 @@ def test_add_world_after_state_change(simulator, compile_to_qubits):
assert board.peek() == [[1]]


@pytest.mark.parametrize("compile_to_qubits", [False, True])
def test_qutrit(compile_to_qubits):
@pytest.mark.parametrize(
("simulator", "compile_to_qubits"),
[
(cirq.Simulator, False),
(cirq.Simulator, True),
# Cannot use SparseSimulator without `compile_to_qubits` due to issue #78.
(alpha.SparseSimulator, True),
],
)
def test_qutrit(simulator, compile_to_qubits):
piece = alpha.QuantumObject("t", 2)
board = alpha.QuantumWorld(piece, compile_to_qubits=compile_to_qubits)
board = alpha.QuantumWorld(
piece, sampler=simulator(), compile_to_qubits=compile_to_qubits
)
assert board.peek() == [[2]]
piece += 1
assert board.peek() == [[0]]
Expand All @@ -65,15 +74,25 @@ def test_qutrit(compile_to_qubits):
assert board.peek() == [[2]]


@pytest.mark.parametrize("compile_to_qubits", [False, True])
def test_enum(compile_to_qubits):
@pytest.mark.parametrize(
("simulator", "compile_to_qubits"),
[
(cirq.Simulator, False),
(cirq.Simulator, True),
# Cannot use SparseSimulator without `compile_to_qubits` due to issue #78.
(alpha.SparseSimulator, True),
],
)
def test_enum(simulator, compile_to_qubits):
class Color(enum.Enum):
RED = 0
YELLOW = 1
GREEN = 2

piece = alpha.QuantumObject("t", Color.YELLOW)
board = alpha.QuantumWorld(piece, compile_to_qubits=compile_to_qubits)
board = alpha.QuantumWorld(
piece, sampler=simulator(), compile_to_qubits=compile_to_qubits
)
assert board.peek() == [[Color.YELLOW]]
piece += Color.YELLOW
assert board.peek() == [[Color.GREEN]]
Expand Down
13 changes: 9 additions & 4 deletions unitary/alpha/quantum_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ class QuantumWorld:
This object also has a history so that effects can be undone.

This object should be initialized with a sampler that determines
how to evaluate the quantum game state. If not specified, this
defaults to the built-in cirq Simulator.
how to evaluate the quantum game state. If not specified, this
defaults to a noiseless simulator optimized for sparse state vectors.
You may also use e.g. cirq.Simulator, a noiseless simulator using
dense state vectors, which natively supports qudits unlike the sparse
simulator.

Setting the `compile_to_qubits` option results in an internal state
representation of ancilla qubits for every qudit in the world. That
Expand All @@ -48,12 +51,14 @@ class QuantumWorld:
def __init__(
self,
objects: Optional[List[QuantumObject]] = None,
sampler=cirq.Simulator(),
compile_to_qubits: bool = False,
sampler: cirq.Sampler = SparseSimulator(),
compile_to_qubits: Optional[bool] = None,
):
self.clear()
self.sampler = sampler
self.use_sparse = isinstance(sampler, SparseSimulator)
if compile_to_qubits is None:
compile_to_qubits = self.use_sparse
self.compile_to_qubits = compile_to_qubits

if isinstance(objects, QuantumObject):
Expand Down
24 changes: 19 additions & 5 deletions unitary/alpha/quantum_world_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ def test_two_qubits(simulator, compile_to_qubits):
def test_two_qutrits(compile_to_qubits):
light = alpha.QuantumObject("yellow", StopLight.YELLOW)
light2 = alpha.QuantumObject("green", StopLight.GREEN)
board = alpha.QuantumWorld([light, light2], compile_to_qubits=compile_to_qubits)
board = alpha.QuantumWorld(
[light, light2], sampler=cirq.Simulator(), compile_to_qubits=compile_to_qubits
)
assert board.peek(convert_to_enum=False) == [[1, 2]]
assert board.peek() == [[StopLight.YELLOW, StopLight.GREEN]]
assert board.peek([light], count=2) == [[StopLight.YELLOW], [StopLight.YELLOW]]
Expand Down Expand Up @@ -630,19 +632,31 @@ def test_combine_incompatibly_sparse_worlds(compile_to_qubits):
world2.combine_with(world1)


@pytest.mark.parametrize("compile_to_qubits", [False, True])
def test_combine_worlds(compile_to_qubits):
@pytest.mark.parametrize(
("simulator", "compile_to_qubits"),
[
(cirq.Simulator, False),
(cirq.Simulator, True),
# Cannot use SparseSimulator without `compile_to_qubits` due to issue #78.
(alpha.SparseSimulator, True),
],
)
def test_combine_worlds(simulator, compile_to_qubits):
l1 = alpha.QuantumObject("l1", Light.GREEN)
l2 = alpha.QuantumObject("l2", Light.RED)
l3 = alpha.QuantumObject("l3", Light.RED)
world1 = alpha.QuantumWorld([l1, l2, l3], compile_to_qubits=compile_to_qubits)
world1 = alpha.QuantumWorld(
[l1, l2, l3], sampler=simulator(), compile_to_qubits=compile_to_qubits
)

# Split and pop to test post-selection after combining
alpha.Split()(l1, l2, l3)
result = world1.pop()

l4 = alpha.QuantumObject("stop_light", StopLight.YELLOW)
world2 = alpha.QuantumWorld([l4], compile_to_qubits=compile_to_qubits)
world2 = alpha.QuantumWorld(
[l4], sampler=simulator(), compile_to_qubits=compile_to_qubits
)
world2.combine_with(world1)

results = world2.peek(count=100)
Expand Down
25 changes: 12 additions & 13 deletions unitary/alpha/qubit_effects_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
import cirq

import unitary.alpha as alpha
from unitary.alpha.sparse_vector_simulator import SparseSimulator


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_flip(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -33,7 +32,7 @@ def test_flip(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_partial_flip(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -44,7 +43,7 @@ def test_partial_flip(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_partial_flip_multiple(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -56,7 +55,7 @@ def test_partial_flip_multiple(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_phase(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -67,7 +66,7 @@ def test_phase(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_partial_phase(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -78,7 +77,7 @@ def test_partial_phase(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_superposition(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", 0)
Expand All @@ -89,7 +88,7 @@ def test_superposition(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_move(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand All @@ -110,7 +109,7 @@ def test_move(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_partial_move(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand All @@ -133,7 +132,7 @@ def test_partial_move(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_phased_move(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand All @@ -154,7 +153,7 @@ def test_phased_move(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_partial_phased_move(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand All @@ -177,7 +176,7 @@ def test_partial_phased_move(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_split(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand All @@ -199,7 +198,7 @@ def test_split(simulator, compile_to_qubits):


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
@pytest.mark.parametrize("simulator", [cirq.Simulator, alpha.SparseSimulator])
def test_phased_split(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece1 = alpha.QuantumObject("a", 1)
Expand Down
30 changes: 24 additions & 6 deletions unitary/alpha/qudit_effects_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import enum
import pytest

import cirq

import unitary.alpha as alpha


Expand All @@ -24,9 +26,17 @@ class StopLight(enum.Enum):
GREEN = 2


@pytest.mark.parametrize("compile_to_qubits", [False, True])
def test_qudit_cycle(compile_to_qubits):
board = alpha.QuantumWorld(compile_to_qubits=compile_to_qubits)
@pytest.mark.parametrize(
("simulator", "compile_to_qubits"),
[
(cirq.Simulator, False),
(cirq.Simulator, True),
# Cannot use SparseSimulator without `compile_to_qubits` due to issue #78.
(alpha.SparseSimulator, True),
],
)
def test_qudit_cycle(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", StopLight.GREEN)
board.add_object(piece)
alpha.QuditCycle(3)(piece)
Expand All @@ -43,9 +53,17 @@ def test_qudit_cycle(compile_to_qubits):
assert all(result == [StopLight.YELLOW] for result in results)


@pytest.mark.parametrize("compile_to_qubits", [False, True])
def test_qudit_flip(compile_to_qubits):
board = alpha.QuantumWorld(compile_to_qubits=compile_to_qubits)
@pytest.mark.parametrize(
("simulator", "compile_to_qubits"),
[
(cirq.Simulator, False),
(cirq.Simulator, True),
# Cannot use SparseSimulator without `compile_to_qubits` due to issue #78.
(alpha.SparseSimulator, True),
],
)
def test_qudit_flip(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("t", StopLight.GREEN)
board.add_object(piece)
alpha.QuditFlip(3, 0, 2)(piece)
Expand Down
3 changes: 1 addition & 2 deletions unitary/alpha/sparse_vector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

Supports standard unitary Cirq gates, plus a post-selection operator.

Does not work with 3+-state qudits. TODO: integrate with qutrit-to-qubit conversion
when that is available.
Does not work with 3+-state qudits.
"""
import cirq
import numpy as np
Expand Down
3 changes: 2 additions & 1 deletion unitary/examples/quantum_rpg/qaracter.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ def qar_sheet(self) -> str:
self.get_object_by_name(self.quantum_object_name(i)).qubit
for i in range(1, self.level + 1)
]
return self.circuit.to_text_diagram(qubit_order=all_qubits)
canonical_circuit = cirq.Circuit(cirq.flatten_op_tree(self.circuit))
return canonical_circuit.to_text_diagram(qubit_order=all_qubits)

def qar_status(self) -> str:
"""Prints out the qaracter's name/class/level and circuit.
Expand Down
Loading
Loading