Quantum Chess REST Client

View on QuantumAI Run in Google Colab View source on GitHub Download notebook

This is a basic client meant to test the server implemented at the end of the Quantum Chess REST API documentation. You must run that previous Colab for this one to work.

Setup

try:
    import unitary
except ImportError:
    !pip install git+https://github.com/quantumlib/unitary -q

try:
    import requests
except ImportError:
    !pip install requests -q

The server for the Quantum Chess Rest API endpoints should provide you with an ngrok url when you run it. Paste the url provided by your server in the form below. If your server is running, the following code should produce the message: "Running Flask on Google Colab!"

url = "http://127.0.0.1:8000/"  # @param {type:"string"}
!curl -s $url
<h1>Running Flask!</h1>

You should be able to see the server output indicting a connection was made.

Initialization

Make a simple request to initialize a board with the starting occupancy state of all pieces. Using the bitboard format, the initial positions of pieces are given by the hex 0xFFFF00000000FFFF. This initializes all squares in ranks 1, 2, 7, and 8 to be occupied.

import requests

init_board_json = {"init_basis_state": 0xFFFF00000000FFFF}
response = requests.post(url + "/quantumboard/init", json=init_board_json)

print(response.content)
b'{"probabilities": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474976645120, "full": 18446462598732906495}\n'

Superposition

With the board initialized, you can execute a few moves to see what happens. You can create superposition by executing a split move from b1 to a3 and c3. Watch the server output to see the execution of this move.

from unitary.quantum_chess.enums import MoveType, MoveVariant
from unitary.quantum_chess.bit_utils import square_to_bit

split_b1_a3_c3 = {
    "square1": square_to_bit("b1"),
    "square2": square_to_bit("a3"),
    "square3": square_to_bit("c3"),
    "type": int(MoveType.SPLIT_JUMP.value),
    "variant": int(MoveVariant.BASIC.value),
}
response = requests.post(url + "/quantumboard/do_move", json=split_b1_a3_c3)
print(response.content)
b'{"result": 1, "probabilities": [1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.531, 0.0, 0.469, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474976317442, "full": 18446462598732906493}\n'

Entanglement

You can see, in the probabilities returned, a roughly 50/50 split for two of the squares. A pawn two-step move, from c2 to c4, will entangle the pawn on c2 with the piece in superposition on a3 and c3.

move_c2_c4 = {
    "square1": square_to_bit("c2"),
    "square2": square_to_bit("c4"),
    "square3": 0,
    "type": int(MoveType.PAWN_TWO_STEP.value),
    "variant": int(MoveVariant.BASIC.value),
}
response = requests.post(url + "/quantumboard/do_move", json=move_c2_c4)
print(response.content)
b'{"result": 1, "probabilities": [1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.496, 1.0, 1.0, 1.0, 1.0, 1.0, 0.504, 0.0, 0.496, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.504, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474909208578, "full": 18446462598732905469}\n'

Measurement

The probability distribution returned doesn't show the entanglement, but it still exists in the underlying state. You can see this by doing a move that forces a measurement. An excluded move from d1 to c2 will force a measurement of the c2 square. In the server output you should see the collapse of the state, with c2, c3, c4, and a3 taking definite 0 or 100% probabilities.

move_d1_c2 = {
    "square1": square_to_bit("d1"),
    "square2": square_to_bit("c2"),
    "square3": 0,
    "type": int(MoveType.JUMP.value),
    "variant": int(MoveVariant.EXCLUDED.value),
}
response = requests.post(url + "/quantumboard/do_move", json=move_d1_c2)
print(response.content)
b'{"result": 1, "probabilities": [1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474909470730, "full": 18446462598800080885}\n'

You can see the entanglement correlation by running the following cell a few times. There should be two different outcomes, the first with both c2 and c3 are 100%, and the second with c4 and a3 both 100%.

response = requests.post(url + "/quantumboard/undo_last_move")
print(response.content)
response = requests.post(url + "/quantumboard/do_move", json=move_d1_c2)
print(response.content)
b'{"result": true, "probabilities": [1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.486, 1.0, 1.0, 1.0, 1.0, 1.0, 0.514, 0.0, 0.486, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.514, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474909208578, "full": 18446462598732905469}\n'
b'{"result": 1, "probabilities": [1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], "empty": 281474909470730, "full": 18446462598800080885}\n'