Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TicTacToe on qubits #70

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
31 changes: 21 additions & 10 deletions unitary/alpha/qudit_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@
#
import numpy as np
import cirq
from unitary.alpha.qudit_state_transform import qudit_to_qubit_unitary


def _nearest_power_of_two_ceiling(qudit_dim: int) -> int:
"""Returns the smallest power of two greater than or equal to qudit_dim."""
if qudit_dim == 0:
return 0
result = 1
while result < qudit_dim:
result = result << 1
return result


class QuditXGate(cirq.Gate):
Expand All @@ -36,7 +47,7 @@ def __init__(
self.destination_state = destination_state

def _qid_shape_(self):
return (self.dimension,)
return (_nearest_power_of_two_ceiling(self.dimension),)

def _unitary_(self):
arr = np.zeros((self.dimension, self.dimension))
Expand All @@ -45,7 +56,7 @@ def _unitary_(self):
for i in range(self.dimension):
if i != self.source_state and i != self.destination_state:
arr[i, i] = 1
return arr
return qudit_to_qubit_unitary(self.dimension, 1, arr)

def _circuit_diagram_info_(self, args):
return f"X({self.source_state}_{self.destination_state})"
Expand All @@ -63,13 +74,13 @@ def __init__(self, dimension: int, addend: int = 1):
self.addend = addend

def _qid_shape_(self):
return (self.dimension,)
return (_nearest_power_of_two_ceiling(self.dimension),)

def _unitary_(self):
arr = np.zeros((self.dimension, self.dimension))
for i in range(self.dimension):
arr[(i + self.addend) % self.dimension, i] = 1
return arr
return qudit_to_qubit_unitary(self.dimension, 1, arr)

def _circuit_diagram_info_(self, args):
return f"[+{self.addend}]"
Expand Down Expand Up @@ -99,7 +110,7 @@ def __init__(self, dimension: int, control_state: int = 1, state: int = 1):
self.control_state = control_state

def _qid_shape_(self):
return (self.dimension, self.dimension)
return (_nearest_power_of_two_ceiling(self.dimension), _nearest_power_of_two_ceiling(self.dimension))

def _unitary_(self):
size = self.dimension * self.dimension
Expand All @@ -111,7 +122,7 @@ def _unitary_(self):
for y in range(self.dimension):
if x != self.control_state or (y != self.state and y != 0):
arr[x * self.dimension + y, x * self.dimension + y] = 1
return arr
return qudit_to_qubit_unitary(self.dimension, 2, arr)


class QuditSwapPowGate(cirq.Gate):
Expand All @@ -134,7 +145,7 @@ def __init__(self, dimension: int, exponent: float = 1):
self.exponent = exponent

def _qid_shape_(self):
return (self.dimension, self.dimension)
return (_nearest_power_of_two_ceiling(self.dimension), _nearest_power_of_two_ceiling(self.dimension))

def _unitary_(self):
size = self.dimension * self.dimension
Expand All @@ -149,7 +160,7 @@ def _unitary_(self):
diag = g * np.cos(np.pi * self.exponent / 2)
arr[x * self.dimension + y, y * self.dimension + x] = coeff
arr[x * self.dimension + y, x * self.dimension + y] = diag
return arr
return qudit_to_qubit_unitary(self.dimension, 2, arr)

def _circuit_diagram_info_(self, args):
if not args.use_unicode_characters:
Expand Down Expand Up @@ -181,7 +192,7 @@ def __init__(self, dimension: int, exponent: float = 1):
self.exponent = exponent

def _qid_shape_(self):
return (self.dimension, self.dimension)
return (_nearest_power_of_two_ceiling(self.dimension), _nearest_power_of_two_ceiling(self.dimension))

def _unitary_(self):
size = self.dimension * self.dimension
Expand All @@ -196,7 +207,7 @@ def _unitary_(self):
arr[x * self.dimension + y, y * self.dimension + x] = coeff
arr[x * self.dimension + y, x * self.dimension + y] = diag

return arr
return qudit_to_qubit_unitary(self.dimension, 2, arr)

def _circuit_diagram_info_(self, args):
return cirq.CircuitDiagramInfo(
Expand Down
1 change: 1 addition & 0 deletions unitary/examples/tictactoe/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class TicTacSquare(enum.Enum):
EMPTY = 0
X = 1
O = 2
PADDING = 3


class TicTacResult(enum.Enum):
Expand Down
7 changes: 4 additions & 3 deletions unitary/examples/tictactoe/tic_tac_split.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from unitary.alpha import QuantumEffect, QuantumObject
from unitary.alpha.qudit_gates import QuditXGate, QuditISwapPowGate
from unitary.examples.tictactoe.enums import TicTacSquare, TicTacRules
from unitary.alpha.qudit_state_transform import qudit_to_qubit_unitary


class QuditSplitGate(cirq.Gate):
Expand All @@ -40,7 +41,7 @@ def __init__(self, square: TicTacSquare):
raise ValueError("Not a valid square: {self.square}")

def _qid_shape_(self):
return (3, 3)
return (4, 4)

def _unitary_(self):
arr = np.zeros((9, 9), dtype=np.complex64)
Expand All @@ -59,7 +60,7 @@ def _unitary_(self):
arr[3, 1] = coeff
arr[3, 3] = diag
arr[1, 1] = diag
return arr
return qudit_to_qubit_unitary(3, 2, arr)

def _circuit_diagram_info_(self, args):
if not args.use_unicode_characters:
Expand All @@ -81,7 +82,7 @@ def __init__(self, tic_tac_type: TicTacSquare, rules: TicTacRules):
self.rules = rules

def num_dimension(self) -> Optional[int]:
return 3
return 4

def num_objects(self) -> Optional[int]:
return 2
Expand Down
2 changes: 2 additions & 0 deletions unitary/examples/tictactoe/tic_tac_toe.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ def print(self) -> str:
output = "\n"
for row in range(3):
for mark in TicTacSquare:
if mark == TicTacSquare.PADDING:
continue
output += " "
for col in range(3):
idx = row * 3 + col
Expand Down