Skip to content

Upgraded to new version of python #2

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

Open
wants to merge 4 commits into
base: refactor-into-subclasses
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.0.1
current_version = 0.0.2
commit = False
tag = False

Expand Down
21 changes: 9 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
[tool.poetry]
name = "tangled-adjudicate"
version = "0.0.1"
version = "0.0.2"
description = "Tangled adjudicators"
authors = ["Geordie Rose <geordie@snowdropquantum.com>"]
license = "MIT"
homepage = "https://www.snowdropquantum.com/"
packages = [
{ include = "tangled_adjudicate" },
{ include = "tests" },
]
packages = [{ include = "tangled_adjudicate" }, { include = "tests" }]

[tool.poetry.dependencies]
python = "^3.8" # You may want to adjust this based on your needs
dwave-ocean-sdk = "*"
dwave-neal = ">=0.6.0"
matplotlib = "*"
gdown = "*"
python = "^3.12" # You may want to adjust this based on your needs
dwave-ocean-sdk = "6.7.1"
dwave-neal = "0.6.0"
matplotlib = "3.10.1"
gdown = "5.2.0"

[tool.poetry.group.dev.dependencies]
# Add development dependencies here if needed
# pytest = "^7.0.0"
pytest = "^7.0.0"
tangled-game-engine = { path = "../../tangled-game-package" }

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

4 changes: 2 additions & 2 deletions tangled_adjudicate/adjudicators/lookup_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ def setup(self, **kwargs) -> None:
if 'data_dir' in kwargs:
if not isinstance(kwargs['data_dir'], str):
raise ValueError("data_dir must be a string")
if not os.path.isdir(kwargs['data_dir']):
raise ValueError(f"Directory not found: {kwargs['data_dir']}")
self.data_dir = kwargs['data_dir']
# Make the data directory if it doesn't exist
os.makedirs(self.data_dir, exist_ok=True)

self._parameters = {'data_dir': self.data_dir}

Expand Down
17 changes: 16 additions & 1 deletion tangled_adjudicate/schrodinger/sparse_matrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from scipy import sparse
from scipy.linalg import eigh, eig
from scipy.sparse.linalg import eigsh
import importlib.resources
import importlib.util
import pathlib


def create_2d_pauli_matrices(verbose=False):
Expand Down Expand Up @@ -76,7 +79,19 @@ def create_pauli_matrices_for_full_size_hamiltonian(n_qubits, verbose=False):
def load_schedule_data(file_path=None, verbose=False):
# data is a numpy array
if file_path is None:
file_path = os.path.join(os.getcwd(), '..', 'schrodinger', 'new_schedule.txt')
# Get the path to the schedule file using package resources
try:
# For Python 3.9+
with importlib.resources.files('tangled_adjudicate.schrodinger').joinpath('new_schedule.txt').open('r') as f:
file_path = str(importlib.resources.files('tangled_adjudicate.schrodinger').joinpath('new_schedule.txt'))
except (ImportError, AttributeError):
# Fallback for older Python versions
package_path = pathlib.Path(importlib.util.find_spec('tangled_adjudicate').origin).parent
file_path = os.path.join(package_path, 'schrodinger', 'new_schedule.txt')

if verbose:
print(f"Using schedule file: {file_path}")

data = np.loadtxt(file_path) # Import SR8 qubit information

# these are both 1001 dimensional row vectors
Expand Down
127 changes: 127 additions & 0 deletions tests/test_adjudicators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import os
import random
import pytest
import traceback
from typing import Dict, List, Tuple, Optional

from tangled_game_engine.tangled_game.game import Game
from tangled_game_engine.tangled_game.game_types import Edge, Vertex

from tangled_adjudicate.adjudicators.lookup_table import LookupTableAdjudicator
from tangled_adjudicate.adjudicators.quantum_annealing import QuantumAnnealingAdjudicator
from tangled_adjudicate.adjudicators.simulated_annealing import SimulatedAnnealingAdjudicator
from tangled_adjudicate.adjudicators.schrodinger import SchrodingerEquationAdjudicator


def play_random_game(graph_id: str = "k_3") -> Dict:
"""
Create a game with the specified graph_id and play it with random legal moves.

Args:
graph_id: The ID of the graph to use for the game

Returns:
The final game state as a dictionary
"""
# Create a new game
game = Game()
game.create_game(graph_id=graph_id, player1_invite="player1", player2_invite="player2")

# Join the game
game.join_game("player1", 1)
game.join_game("player2", 2)

# Play the game until it's over
while not game.is_game_over():
# Get legal moves for the current player
current_player_id = game.player1_id if game.current_player_index == 1 else game.player2_id
legal_moves = game.get_legal_moves(current_player_id)

# Filter out quit moves
legal_moves = [move for move in legal_moves if move[0] != Game.MoveType.QUIT.value]

# Choose a random move
if legal_moves:
move = random.choice(legal_moves)
game.make_move(current_player_id, move[0], move[1], move[2])

# Return the final game state
return game.get_game_state()


def test_adjudicators():
"""
Test all adjudicators with a random game on the k_3 graph.
"""
# Set random seed for reproducibility
random.seed(42)

# Play a random game
game_state = play_random_game(graph_id="k_3")

# Print the final game state for debugging
print("\nFinal Game State:")
print(f"Player 1 node: {game_state['player1_node']}")
print(f"Player 2 node: {game_state['player2_node']}")
print(f"Edges: {game_state['edges']}")

# Create a temporary directory for lookup table data
temp_dir = os.path.join(os.path.dirname(__file__), "temp_data")
os.makedirs(temp_dir, exist_ok=True)

# Test each adjudicator
adjudicators = [
(LookupTableAdjudicator(), {"data_dir": temp_dir}),
(SimulatedAnnealingAdjudicator(), {}),
(SchrodingerEquationAdjudicator(), {}),
# (QuantumAnnealingAdjudicator(), {"use_mock": True, "graph_number": 2, "data_dir": temp_dir})
]

results = []

for adjudicator, params in adjudicators:
try:
# Setup the adjudicator
adjudicator.setup(**params)

# Adjudicate the game state
result = adjudicator.adjudicate(game_state)

# Store the result
results.append(result)

# Print the result
print(f"\n{result['adjudicator']} Result:")
print(f"Winner: {result['winner']}")
if result['score'] is not None:
print(f"Score: {result['score']}")

# Assert that the result has the expected fields
assert 'winner' in result, f"{result['adjudicator']} result missing 'winner' field"
assert 'game_state' in result, f"{result['adjudicator']} result missing 'game_state' field"
assert 'adjudicator' in result, f"{result['adjudicator']} result missing 'adjudicator' field"

except Exception as e:
# Print the full traceback
print(f"\nError in {adjudicator.__class__.__name__}:")
traceback.print_exc()
pytest.fail(f"Adjudicator {adjudicator.__class__.__name__} failed: {str(e)}")

# Compare results from different adjudicators
if len(results) > 1:
print("\nComparing adjudicator results:")
for i in range(len(results)):
for j in range(i+1, len(results)):
adj1 = results[i]['adjudicator']
adj2 = results[j]['adjudicator']
winner1 = results[i]['winner']
winner2 = results[j]['winner']

print(f"{adj1} vs {adj2}: {winner1} vs {winner2}")

# Note: We don't assert equality because different adjudicators might give different results
# This is just for information


if __name__ == "__main__":
test_adjudicators()