Skip to content

Commit

Permalink
update flying general check
Browse files Browse the repository at this point in the history
  • Loading branch information
Pengfei Chen committed Oct 30, 2023
1 parent ab75eb3 commit 307f5c5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
28 changes: 27 additions & 1 deletion unitary/examples/quantum_chinese_chess/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,33 @@ def flying_general_check(self) -> bool:
if len(quantum_pieces) == 0:
# If there are no pieces between two KINGs, the check successes. Game ends.
return True
# TODO(): add check when there are quantum pieces in between.
# When there are quantum pieces in between, the check successes (and game ends)
# if there are at lease one occupied path piece.
capture_ancilla = self.board._add_ancilla("flying_general_check")
control_objects = [self.board[path] for path in quantum_pieces]
conditions = [0] * len(control_objects)
alpha.quantum_if(*control_objects).equals(*conditions).apply(alpha.Flip())(
capture_ancilla
)
could_capture = self.board.pop([capture_ancilla])[0]
if could_capture:
# Force measure all path pieces to be empty.
for path_piece in control_objects:
self.board.force_measurement(path_piece, 0)
path_piece.reset()

# Let the general/king fly, i.e. the opposite king will capture the current king.
current_king = self.board[self.king_locations[self.current_player]]
oppsite_king = self.board[self.king_locations[1 - self.current_player]]
Jump(MoveVariant.CLASSICAL)(oppsite_king, current_king)
print("==== FLYING GENERAL ! ====")
return True
else:
# TODO(): we are leaving the path pieces unchanged in entangled state. Maybe
# better to force measure them? One option is to randomly chosing one path piece
# and force measure it to be occupied.
print("==== General not flies yet ! ====")
return False

def sample(self, repetitions: int) -> List[int]:
"""Sample the current board by the given `repetitions`.
Expand Down
35 changes: 35 additions & 0 deletions unitary/examples/quantum_chinese_chess/board_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
)
from unitary.examples.quantum_chinese_chess.board import Board
from unitary.examples.quantum_chinese_chess.piece import Piece
from unitary.examples.quantum_chinese_chess.test_utils import (
locations_to_bitboard,
assert_samples_in,
assert_sample_distribution,
get_board_probability_distribution,
set_board,
)
from unitary import alpha


def test_init_with_default_fen():
Expand Down Expand Up @@ -155,3 +163,30 @@ def test_flying_general_check():
board.board["e3"].reset()
board.board["e6"].reset()
assert board.flying_general_check() == True

# When there are quantum pieces in between.
board = set_board(["a3", "a4", "e0", "e9"])
board.king_locations = ["e0", "e9"]
board.current_player = 0 # i.e. RED
world = board.board
alpha.PhasedSplit()(world["a3"], world["c3"], world["e3"])
world["e3"].is_entangled = True
alpha.PhasedSplit()(world["a4"], world["c4"], world["e4"])
world["e4"].is_entangled = True

result = board.flying_general_check()
# We check the ancilla to learn whether the general/king flies or not.
captured = world.post_selection[world["ancilla_ancilla_flying_general_check_0_0"]]
if captured:
assert result
assert_samples_in(board, {locations_to_bitboard(["c3", "c4", "e0"]): 1.0})
else:
assert not result
assert_sample_distribution(
board,
{
locations_to_bitboard(["e0", "e9", "e3", "e4"]): 1.0 / 3,
locations_to_bitboard(["e0", "e9", "e3", "c4"]): 1.0 / 3,
locations_to_bitboard(["e0", "e9", "c3", "e4"]): 1.0 / 3,
},
)

0 comments on commit 307f5c5

Please sign in to comment.