Skip to content

Commit

Permalink
Allow quantum if with multiple effects
Browse files Browse the repository at this point in the history
- Note that all effects must apply to the same qubits.
  • Loading branch information
dstrain115 committed Dec 15, 2023
1 parent e54c205 commit cd3aca7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
15 changes: 10 additions & 5 deletions unitary/alpha/quantum_effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class QuantumThen(QuantumEffect):
def __init__(self, *objects: "QuantumObject"):
self.control_objects = list(objects)
self.condition = [1] * len(self.control_objects)
self.then_effect = None
self.then_effects = None

def equals(
self, *conditions: Union[enum.Enum, int, Sequence[Union[enum.Enum, int]]]
Expand All @@ -124,9 +124,13 @@ def then(self, effect: "QuantumEffect"):
"""Use `apply(effect)` instead."""
return self.apply(effect)

def apply(self, effect: "QuantumEffect"):
"""Applies a QuantumEffect conditionally to the specified qubits."""
self.then_effect = effect
def apply(self, *effects: "QuantumEffect"):
"""Applies a QuantumEffect conditionally to the specified qubits.
If multiple effects are specified, they will all be applied
(to the same qubits).
"""
self.then_effects = list(effects)
return self

def effect(self, *objects: "QuantumObject"):
Expand All @@ -136,7 +140,8 @@ def effect(self, *objects: "QuantumObject"):
if cond == 0 and self.control_objects[idx].num_states == 2:
yield cirq.X(self.control_objects[idx].qubit)

for op in self.then_effect.effect(*objects):
for effect in self.then_effects:
for op in effect.effect(*objects):
yield op.controlled_by(*[q.qubit for q in self.control_objects])

# For anti-controls, add an X after the controlled operation
Expand Down
16 changes: 16 additions & 0 deletions unitary/alpha/quantum_effect_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ def test_anti_control(simulator, compile_to_qubits):
assert (result[0] == 1 for result in results)


@pytest.mark.parametrize("compile_to_qubits", [False, True])
@pytest.mark.parametrize("simulator", [cirq.Simulator, SparseSimulator])
def test_multiple_effects_quantum_if(simulator, compile_to_qubits):
board = alpha.QuantumWorld(sampler=simulator(), compile_to_qubits=compile_to_qubits)
piece = alpha.QuantumObject("q0", 1)
piece2 = alpha.QuantumObject("q1", 0)
board.add_object(piece)
board.add_object(piece2)
alpha.quantum_if(piece).apply(
alpha.Flip(effect_fraction=0.5), alpha.Flip(effect_fraction=0.5)
)(piece2)

# Test that results are as expected
results = board.peek([piece, piece2], count=100)


def test_no_world():
piece = alpha.QuantumObject("q0", 1)
with pytest.raises(ValueError, match="must be added to a QuantumWorld"):
Expand Down

0 comments on commit cd3aca7

Please sign in to comment.