Skip to content

Commit

Permalink
Merge pull request #172 from madcpf/moves2
Browse files Browse the repository at this point in the history
[Quantum Chinese Chess] Implement more move types
  • Loading branch information
madcpf authored Dec 8, 2023
2 parents abb7a0b + b231ba7 commit e54c205
Show file tree
Hide file tree
Showing 4 changed files with 1,063 additions and 10 deletions.
19 changes: 11 additions & 8 deletions unitary/alpha/quantum_effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
from typing import Iterator, Optional, Sequence, Union
from typing import Iterator, Optional, Sequence, Union, TYPE_CHECKING
import abc
import enum

import cirq

if TYPE_CHECKING:
from unitary.alpha.quantum_object import QuantumObject


def _to_int(value: Union[enum.Enum, int]) -> int:
return value.value if isinstance(value, enum.Enum) else value


class QuantumEffect(abc.ABC):
@abc.abstractmethod
def effect(self, *objects) -> Iterator[cirq.Operation]:
def effect(self, *objects: "QuantumObject") -> Iterator[cirq.Operation]:
"""Apply the Quantum Effect to the QuantumObjects."""

def num_dimension(self) -> Optional[int]:
Expand All @@ -39,7 +42,7 @@ def num_objects(self) -> Optional[int]:
"""
return None

def _verify_objects(self, *objects):
def _verify_objects(self, *objects: "QuantumObject"):
if self.num_objects() is not None and len(objects) != self.num_objects():
raise ValueError(f"Cannot apply effect to {len(objects)} qubits.")

Expand All @@ -56,7 +59,7 @@ def _verify_objects(self, *objects):
"Object must be added to a QuantumWorld to apply effects."
)

def __call__(self, *objects):
def __call__(self, *objects: "QuantumObject"):
"""Apply the Quantum Effect to the objects."""
self._verify_objects(*objects)
world = objects[0].world
Expand Down Expand Up @@ -86,15 +89,15 @@ class QuantumIf:
must equal the number of control qubits.
"""

def effect(self, *objects) -> Iterator[cirq.Operation]:
def effect(self, *objects: "QuantumObject") -> Iterator[cirq.Operation]:
return iter(())

def __call__(self, *objects):
def __call__(self, *objects: "QuantumObject"):
return QuantumThen(*objects)


class QuantumThen(QuantumEffect):
def __init__(self, *objects):
def __init__(self, *objects: "QuantumObject"):
self.control_objects = list(objects)
self.condition = [1] * len(self.control_objects)
self.then_effect = None
Expand Down Expand Up @@ -126,7 +129,7 @@ def apply(self, effect: "QuantumEffect"):
self.then_effect = effect
return self

def effect(self, *objects):
def effect(self, *objects: "QuantumObject"):
"""A Quantum if/then produces a controlled operation."""
# For anti-controls, add an X before the controlled operation
for idx, cond in enumerate(self.condition):
Expand Down
24 changes: 22 additions & 2 deletions unitary/examples/quantum_chinese_chess/chess.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@
MoveType,
MoveVariant,
)
from unitary.examples.quantum_chinese_chess.move import Jump
from unitary.examples.quantum_chinese_chess.move import (
Jump,
SplitJump,
MergeJump,
Slide,
SplitSlide,
MergeSlide,
CannonFire,
)
import readline

# List of accepable commands.
Expand Down Expand Up @@ -390,6 +398,7 @@ def apply_move(self, str_to_parse: str) -> None:
print(move_type, " ", move_variant)

# Apply the move accoding to its type.
# TODO(): using match...case... when python 3.11 satisfies the dependency.
if move_type == MoveType.CLASSICAL:
if source_0.type_ == Type.KING:
# Update the locations of KING.
Expand All @@ -402,7 +411,18 @@ def apply_move(self, str_to_parse: str) -> None:
Jump(move_variant)(source_0, target_0)
elif move_type == MoveType.JUMP:
Jump(move_variant)(source_0, target_0)
# TODO(): apply other move types.
elif move_type == MoveType.SLIDE:
Slide(quantum_pieces_0, move_variant)(source_0, target_0)
elif move_type == MoveType.SPLIT_JUMP:
SplitJump()(source_0, target_0, target_1)
elif move_type == MoveType.SPLIT_SLIDE:
SplitSlide(quantum_pieces_0, quantum_pieces_1)(source_0, target_0, target_1)
elif move_type == MoveType.MERGE_JUMP:
MergeJump()(source_0, source_1, target_0)
elif move_type == MoveType.MERGE_SLIDE:
MergeSlide(quantum_pieces_0, quantum_pieces_1)(source_0, source_1, target_0)
elif move_type == MoveType.CANNON_FIRE:
CannonFire(classical_pieces_0, quantum_pieces_0)(source_0, target_0)

def next_move(self) -> Tuple[bool, str]:
"""Check if the player wants to exit or needs help message. Otherwise parse and apply the move.
Expand Down
Loading

0 comments on commit e54c205

Please sign in to comment.