def test_2block_ks_castle(board): """Kingside castling move blocked by 2 pieces in superposition.""" b = board.with_state(u.squares_to_bitboard(['e8', 'f6', 'g6', 'h8'])) did_it_move = b.perform_moves( 'f6f7f8:SPLIT_JUMP:BASIC', 'g6g7g8:SPLIT_JUMP:BASIC', 'e8g8:KS_CASTLE:BASIC', ) if did_it_move: possibilities = [u.squares_to_bitboard(['g8', 'f7', 'g7', 'f8'])] else: possibilities = [ u.squares_to_bitboard(['e8', 'f8', 'g7', 'h8']), u.squares_to_bitboard(['e8', 'f7', 'g8', 'h8']), u.squares_to_bitboard(['e8', 'f8', 'g8', 'h8']), ] assert_samples_in(b, possibilities)
def test_merge_move(board): """Splits piece on a1 to b1 and c1 and then merges back to a1.""" b = board.with_state(u.squares_to_bitboard(['a1'])) b.do_move( move.Move('a1', 'b1', target2='c1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) b.do_move( move.Move('b1', 'a1', source2='c1', move_type=enums.MoveType.MERGE_JUMP, move_variant=enums.MoveVariant.BASIC)) assert_samples_in(b, [u.squares_to_bitboard(['a1'])]) assert b.get_full_squares_bitboard() == 1
def test_pawn_capture(board): """Tests pawn capture with entanglement. Rook on a3 => a4/a5 and rook on c3 => c4/c5. Pawn on b3 attempts to capture both rooks. The first capture should put the pawn in super-position, and the second should force a measurement. """ b = board.with_state(u.squares_to_bitboard(['a3', 'b3', 'c3'])) # Capture and put the pawn in superposition assert b.perform_moves('a3a4a5:SPLIT_JUMP:BASIC', 'b3a4:PAWN_CAPTURE:BASIC') possibilities = [ u.squares_to_bitboard(['a5', 'b3', 'c3']), u.squares_to_bitboard(['a4', 'c3']), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, qb.square_to_bit('a5')) assert_fifty_fifty(probs, qb.square_to_bit('a4')) assert_fifty_fifty(probs, qb.square_to_bit('b3')) did_it_move = b.perform_moves('c3c4c5:SPLIT_JUMP:BASIC', 'b3c4:PAWN_CAPTURE:BASIC') if did_it_move: possibilities = [ u.squares_to_bitboard(['a5', 'b3', 'c5']), u.squares_to_bitboard(['a5', 'c4']), ] else: possibilities = [ u.squares_to_bitboard(['a4', 'c4']), u.squares_to_bitboard(['a4', 'c5']), ] assert_samples_in(b, possibilities)
def test_a6_alternate(board): b = board.with_state( u.squares_to_bitboard( ['a2', 'f2', 'g2', 'h2', 'g3', 'c6', 'h6', 'f7', 'g7', 'h7', 'h8'])) did_it_move = b.perform_moves( 'a2a8:SLIDE:BASIC', 'c6b8d8:SPLIT_JUMP:BASIC', 'a8b8:SLIDE:CAPTURE', 'h6d6:SLIDE:BASIC', 'b8h8:SLIDE:CAPTURE', ) if did_it_move: expected = u.squares_to_bitboard( ['f2', 'g2', 'h2', 'g3', 'd6', 'f7', 'g7', 'h7', 'h8']) else: expected = u.squares_to_bitboard( ['b8', 'f2', 'g2', 'h2', 'g3', 'd8', 'd6', 'f7', 'g7', 'h7', 'h8']) assert_samples_in(b, [expected])
def test_capture_ep2(): """Tests capture en passant. Splits b8 to a6/c6. Move c7 to c5 and perform en passant on c6. This should either capture the knight or the pawn. """ b = qb.CirqBoard(u.squares_to_bitboard(['b8', 'b5', 'c7'])) did_it_move = b.perform_moves( 'b8a6c6:SPLIT_JUMP:BASIC', 'c7c5:PAWN_TWO_STEP:BASIC', 'b5c6:PAWN_EP:CAPTURE', ) assert did_it_move possibilities = [ u.squares_to_bitboard(['c6', 'c7']), u.squares_to_bitboard(['c6', 'a6']), ] assert_samples_in(b, possibilities)
def test_blocked_slide_clear(board): """Blocked slide with 100% success Tests a piece "blocked" by itself. Position: Ra1. Moves: Ra1^a3a4 Ra3a8 """ b = board.with_state(u.squares_to_bitboard(['a1'])) assert b.perform_moves( 'a1a3a4:SPLIT_SLIDE:BASIC', 'a3a8:SLIDE:BASIC', ) samples = b.sample(100) possibilities = [ u.squares_to_bitboard(['a4']), u.squares_to_bitboard(['a8']), ] assert all(sample in possibilities for sample in samples)
def test_capture_ep2(): """Tests capture en passant. Splits b8 to a6/c6. Move c7 to c5 and perform en passant on c6. This should either capture the knight or the pawn. """ b = simulator(u.squares_to_bitboard(["b8", "b5", "c7"])) did_it_move = b.perform_moves( "b8^a6c6:SPLIT_JUMP:BASIC", "c7c5:PAWN_TWO_STEP:BASIC", "b5c6:PAWN_EP:CAPTURE", ) assert did_it_move possibilities = [ u.squares_to_bitboard(["c6", "c7"]), u.squares_to_bitboard(["c6", "a6"]), ] assert_samples_in(b, possibilities)
def test_undo_last_move(): # TODO (cantwellc) more comprehensive tests b = qb.CirqBoard(u.squares_to_bitboard(['a2'])) assert b.perform_moves('a2a4:PAWN_TWO_STEP:BASIC') probs = b.get_probability_distribution(1000) assert_prob_about(probs, qb.square_to_bit('a4'), 1.0) assert b.undo_last_move() probs = b.get_probability_distribution(1000) assert_prob_about(probs, qb.square_to_bit('a2'), 1.0)
def test_capture(board): """Splits piece from b1 to c1 and d1 then attempts a capture on a1.""" b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('c1', 'a1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.CAPTURE)) if did_it_move: expected = u.squares_to_bitboard(['a1']) else: expected = u.squares_to_bitboard(['a1', 'd1']) assert_samples_in(b, [expected])
def test_a6_alternate(board): b = board( u.squares_to_bitboard( ["a2", "f2", "g2", "h2", "g3", "c6", "h6", "f7", "g7", "h7", "h8"])) did_it_move = b.perform_moves( "a2a8:SLIDE:BASIC", "c6^b8d8:SPLIT_JUMP:BASIC", "a8b8:SLIDE:CAPTURE", "h6d6:SLIDE:BASIC", "b8h8:SLIDE:CAPTURE", ) if did_it_move: expected = u.squares_to_bitboard( ["f2", "g2", "h2", "g3", "d6", "f7", "g7", "h7", "h8"]) else: expected = u.squares_to_bitboard( ["b8", "f2", "g2", "h2", "g3", "d8", "d6", "f7", "g7", "h7", "h8"]) assert_samples_in(b, [expected])
def test_jump_with_successful_measurement_outcome(board): b = board(u.squares_to_bitboard(["b1", "c2"])) b.do_move( move.Move( "b1", "a3", target2="c3", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, )) b.do_move( move.Move( "c2", "c3", move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.EXCLUDED, measurement=1, )) assert_samples_in(b, [u.squares_to_bitboard(["c3", "a3"])])
def test_1block_ks_castle(board): """Kingside castling move blocked by 1 piece in superposition.""" b = board.with_state(u.squares_to_bitboard(['e1', 'f3', 'h1'])) b.do_move( move.Move('f3', 'f2', target2='f1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('e1', 'g1', move_type=enums.MoveType.KS_CASTLE, move_variant=enums.MoveVariant.BASIC)) if did_it_move: expected = u.squares_to_bitboard(['f1', 'f2', 'g1']) else: expected = u.squares_to_bitboard(['e1', 'f1', 'h1']) assert_samples_in(b, [expected])
def test_a9(board): b = qb.CirqBoard( u.squares_to_bitboard( ['h1', 'e2', 'f2', 'g2', 'e3', 'h3', 'g6', 'h6', 'c7'])) did_it_move = b.perform_moves( 'e2e3:SLIDE:CAPTURE', 'c7^f4h2:SPLIT_SLIDE:BASIC', 'e3h6:SLIDE:CAPTURE', ) if did_it_move: possibilities = [ u.squares_to_bitboard(['h1', 'f2', 'g2', 'h3', 'g6', 'h6', 'h2']) ] else: possibilities = [ u.squares_to_bitboard( ['h1', 'f2', 'g2', 'e3', 'h3', 'g6', 'h6', 'f4']) ] assert_samples_in(b, possibilities)
def test_a9(board): b = board( u.squares_to_bitboard( ["h1", "e2", "f2", "g2", "e3", "h3", "g6", "h6", "c7"])) did_it_move = b.perform_moves( "e2e3:SLIDE:CAPTURE", "c7^f4h2:SPLIT_SLIDE:BASIC", "e3h6:SLIDE:CAPTURE", ) if did_it_move: possibilities = [ u.squares_to_bitboard(["h1", "f2", "g2", "h3", "g6", "h6", "h2"]) ] else: possibilities = [ u.squares_to_bitboard( ["h1", "f2", "g2", "e3", "h3", "g6", "h6", "f4"]) ] assert_samples_in(b, possibilities)
def test_split_both_sides(board): """ Tests a split slide move where both paths of the slide are blocked in superposition. The piece will split from a1 to a5/e1. The squares c1 and d1 will block one side of the path in superposition. The square a3 will be blocked on the other path. This will create a lop-sided distribution to test multi-square paths. """ b = board.with_state(u.squares_to_bitboard(['a1', 'b3', 'c3', 'd3'])) assert b.perform_moves( 'b3a3b4:SPLIT_JUMP:BASIC', 'c3c2c1:SPLIT_JUMP:BASIC', 'd3d2d1:SPLIT_JUMP:BASIC', 'a1a5e1:SPLIT_SLIDE:BASIC', ) samples = b.sample(1000) assert len(samples) == 1000 possibilities = [ # a1/a5/e1 a3/b4 c1/c2 d1/d2 u.squares_to_bitboard(['a1', 'a3', 'c1', 'd1']), u.squares_to_bitboard(['a1', 'a3', 'c1', 'd2']), u.squares_to_bitboard(['a1', 'a3', 'c2', 'd1']), u.squares_to_bitboard(['e1', 'a3', 'c2', 'd2']), u.squares_to_bitboard(['a5', 'b4', 'c1', 'd1']), u.squares_to_bitboard(['a5', 'b4', 'c1', 'd2']), u.squares_to_bitboard(['a5', 'b4', 'c2', 'd1']), u.squares_to_bitboard(['a5', 'b4', 'c2', 'd2']), u.squares_to_bitboard(['e1', 'b4', 'c2', 'd2']), ] assert (all(sample in possibilities for sample in samples)) probs = b.get_probability_distribution(25000) assert_fifty_fifty(probs, qb.square_to_bit('a3')) assert_fifty_fifty(probs, qb.square_to_bit('b4')) assert_fifty_fifty(probs, qb.square_to_bit('c1')) assert_fifty_fifty(probs, qb.square_to_bit('c2')) assert_fifty_fifty(probs, qb.square_to_bit('d1')) assert_fifty_fifty(probs, qb.square_to_bit('d2')) assert_prob_about(probs, qb.square_to_bit('a1'), 0.375) assert_prob_about(probs, qb.square_to_bit('e1'), 0.1875) assert_prob_about(probs, qb.square_to_bit('a5'), 0.4375)
def test_a2(board): b = board( u.squares_to_bitboard( ["a8", "b8", "g8", "f7", "g7", "g3", "f2", "f3", "h1"])) did_it_move = b.perform_moves( "h1^h7h8:SPLIT_SLIDE:BASIC", "g8f8:JUMP:BASIC", "h8f8:SLIDE:CAPTURE", ) if did_it_move: possibilities = [ u.squares_to_bitboard( ["a8", "b8", "f8", "f7", "g7", "g3", "f2", "f3"]) ] else: possibilities = [ u.squares_to_bitboard( ["a8", "b8", "f8", "f7", "g7", "g3", "f2", "f3", "h7"]) ] assert_samples_in(b, possibilities)
def test_capture_ep(): """Tests capture en passant. Splits b8 to a6/c6. Capture a6 with b5 pawn to put the source pawn into superposition. Finally, move c7 to c5 and perform en passant on c6. """ b = simulator(u.squares_to_bitboard(["b8", "b5", "c7"])) did_it_move = b.perform_moves( "b8^a6c6:SPLIT_JUMP:BASIC", "b5a6:PAWN_CAPTURE:BASIC", "c7c5:PAWN_TWO_STEP:BASIC", "b5c6:PAWN_EP:CAPTURE", ) if did_it_move: expected = u.squares_to_bitboard(["c6", "c7"]) else: expected = u.squares_to_bitboard(["a6", "c5"]) assert_samples_in(b, [expected])
def test_a2(board): b = board.with_state( u.squares_to_bitboard( ['a8', 'b8', 'g8', 'f7', 'g7', 'g3', 'f2', 'f3', 'h1'])) did_it_move = b.perform_moves( 'h1^h7h8:SPLIT_SLIDE:BASIC', 'g8f8:JUMP:BASIC', 'h8f8:SLIDE:CAPTURE', ) if did_it_move: possibilities = [ u.squares_to_bitboard( ['a8', 'b8', 'f8', 'f7', 'g7', 'g3', 'f2', 'f3']) ] else: possibilities = [ u.squares_to_bitboard( ['a8', 'b8', 'f8', 'f7', 'g7', 'g3', 'f2', 'f3', 'h7']) ] assert_samples_in(b, possibilities)
def test_caching_accumulations_same_repetition_cached(board): b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) probs1 = b.get_probability_distribution(100) probs2 = b.get_probability_distribution(100) assert probs1 == probs2
def test_capture_ep(): """Tests capture en passant. Splits b8 to a6/c6. Capture a6 with b5 pawn to put the source pawn into superposition. Finally, move c7 to c5 and perform en passant on c6. """ b = qb.CirqBoard(u.squares_to_bitboard(['b8', 'b5', 'c7'])) did_it_move = b.perform_moves( 'b8a6c6:SPLIT_JUMP:BASIC', 'b5a6:PAWN_CAPTURE:BASIC', 'c7c5:PAWN_TWO_STEP:BASIC', 'b5c6:PAWN_EP:CAPTURE', ) if did_it_move: expected = u.squares_to_bitboard(['c6', 'c7']) else: expected = u.squares_to_bitboard(['a6', 'c5']) assert_samples_in(b, [expected])
def test_path_qubits(): """Source and target should be in the same line, otherwise ValueError should be returned.""" b = qb.CirqBoard( u.squares_to_bitboard(['a1', 'b3', 'c4', 'd5', 'e6', 'f7'])) assert b.path_qubits("b3", "f7") == [bit_to_qubit(square_to_bit('c4')), \ bit_to_qubit(square_to_bit('d5')), \ bit_to_qubit(square_to_bit('e6'))] with pytest.raises(ValueError): b.path_qubits("a1", "b3") with pytest.raises(ValueError): b.path_qubits("c4", "a1")
def test_merge_move(board): """Splits piece on a1 to b1 and c1 and then merges back to a1.""" b = board(u.squares_to_bitboard(["a1"])) b.do_move( move.Move( "a1", "b1", target2="c1", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, )) b.do_move( move.Move( "b1", "a1", source2="c1", move_type=enums.MoveType.MERGE_JUMP, move_variant=enums.MoveVariant.BASIC, )) assert_samples_in(b, [u.squares_to_bitboard(["a1"])]) assert b.get_full_squares_bitboard() == 1
def test_a10(board): b = board.with_state( u.squares_to_bitboard([ 'd1', 'f1', 'g1', 'f2', 'g2', 'h2', 'd3', 'd4', 'd5', 'd6', 'e6', 'g6', 'h6', 'g7', 'b8', 'f8' ])) did_it_move = b.perform_moves( 'd3^c5e5:SPLIT_JUMP:BASIC', 'g6h7:JUMP:BASIC', 'c5e5^d7:MERGE_JUMP:BASIC', 'b8d8:SLIDE:BASIC', 'd7f8:JUMP:CAPTURE', ) assert did_it_move possibilities = [ u.squares_to_bitboard([ 'd1', 'f1', 'g1', 'f2', 'g2', 'h2', 'd4', 'd5', 'd6', 'e6', 'h7', 'h6', 'g7', 'd8', 'f8' ]) ] assert_samples_in(b, possibilities)
def test_blocked_ep(): """Tests blocked en passant. Splits c4 to b6 and d6. Moves a pawn through the piece on d6. Attempts to en passant the d-pawn using blocked e.p. """ b = qb.CirqBoard(u.squares_to_bitboard(['c4', 'c5', 'd7'])) did_it_move = b.perform_moves( 'c4d6b6:SPLIT_JUMP:BASIC', 'd7d5:PAWN_TWO_STEP:BASIC', 'c5d6:PAWN_EP:EXCLUDED', ) if did_it_move: possibilities = [ u.squares_to_bitboard(['b6', 'd6']), ] else: possibilities = [ u.squares_to_bitboard(['c5', 'd6', 'd7']), ] assert_samples_in(b, possibilities)
def test_slide_with_two_path_qubits_coherence(): """Tests that a path ancilla does not mess up split/merge coherence. Position: Qd1, Bf1, Ng1. See https://github.com/quantumlib/ReCirq/issues/193. """ b = simulator(u.squares_to_bitboard(['d1', 'f1', 'g1'])) assert b.perform_moves( 'g1^h3f3:SPLIT_JUMP:BASIC', 'f1^e2b5:SPLIT_SLIDE:BASIC', 'd1h5:SLIDE:BASIC', 'd1h5:SLIDE:BASIC', 'd1h5:SLIDE:BASIC', 'd1h5:SLIDE:BASIC', 'h3f3^g1:MERGE_JUMP:BASIC', ) assert_sample_distribution( b, { u.squares_to_bitboard(['d1', 'b5', 'g1']): 1 / 2, u.squares_to_bitboard(['d1', 'e2', 'g1']): 1 / 2, })
def test_blocked_ep(): """Tests blocked en passant. Splits c4 to b6 and d6. Moves a pawn through the piece on d6. Attempts to en passant the d-pawn using blocked e.p. """ b = simulator(u.squares_to_bitboard(["c4", "c5", "d7"])) did_it_move = b.perform_moves( "c4^d6b6:SPLIT_JUMP:BASIC", "d7d5:PAWN_TWO_STEP:BASIC", "c5d6:PAWN_EP:EXCLUDED", ) if did_it_move: possibilities = [ u.squares_to_bitboard(["b6", "d6"]), ] else: possibilities = [ u.squares_to_bitboard(["c5", "d6", "d7"]), ] assert_samples_in(b, possibilities)
def test_exclusion(board): """Splits piece b1 to c1 and d1 then tries a excluded move from a1 to c1.""" b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('a1', 'c1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.EXCLUDED)) samples = b.sample(20) if did_it_move: expected = u.squares_to_bitboard(['c1', 'd1']) assert all(sample == expected for sample in samples) else: expected = u.squares_to_bitboard(['a1', 'c1']) assert all(sample == expected for sample in samples)
def test_entangled_qs_castle(board): """Queenside castling move with b-square blocked by superposition. This should entangle the castling rook/king with the piece. """ b = board.with_state(u.squares_to_bitboard(['e1', 'b3', 'a1'])) b.do_move( move.Move('b3', 'b2', target2='b1', move_type=enums.MoveType.SPLIT_SLIDE, move_variant=enums.MoveVariant.BASIC)) assert b.do_move( move.Move('e1', 'c1', move_type=enums.MoveType.QS_CASTLE, move_variant=enums.MoveVariant.BASIC)) possibilities = [ u.squares_to_bitboard(['a1', 'b1', 'e1']), u.squares_to_bitboard(['c1', 'b2', 'd1']) ] assert_samples_in(b, possibilities)
def test_path_qubits(): """Source and target should be in the same line, otherwise ValueError should be returned.""" b = qb.CirqBoard( u.squares_to_bitboard(["a1", "b3", "c4", "d5", "e6", "f7"])) assert b.path_qubits("b3", "f7") == [ bit_to_qubit(square_to_bit("c4")), bit_to_qubit(square_to_bit("d5")), bit_to_qubit(square_to_bit("e6")), ] with pytest.raises(ValueError): b.path_qubits("a1", "b3") with pytest.raises(ValueError): b.path_qubits("c4", "a1")
def test_split_one_slide(board): """Tests a split slide with one blocked path. a1 will split to a3 and c1 with square a2 blocked in superposition. """ b = board.with_state(u.squares_to_bitboard(['a1', 'b2'])) assert b.perform_moves( 'b2a2c2:SPLIT_JUMP:BASIC', 'a1a3c1:SPLIT_SLIDE:BASIC', ) samples = b.sample(100) possibilities = [ u.squares_to_bitboard(['c1', 'a2']), u.squares_to_bitboard(['a3', 'c2']), u.squares_to_bitboard(['c1', 'c2']), ] assert (all(sample in possibilities for sample in samples)) probs = b.get_probability_distribution(10000) assert_fifty_fifty(probs, qb.square_to_bit('a2')) assert_fifty_fifty(probs, qb.square_to_bit('c2')) assert_prob_about(probs, qb.square_to_bit('a3'), 0.25) assert_prob_about(probs, qb.square_to_bit('c1'), 0.75)