Skip to content

Commit

Permalink
Merge pull request #74 from GamesCrafters/ants/generalSolverErrors
Browse files Browse the repository at this point in the history
Error handling in GeneralSolver
  • Loading branch information
Ant1ng2 authored Dec 23, 2020
2 parents 835885f + ebd3a83 commit 9a814d9
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
15 changes: 11 additions & 4 deletions puzzlesolver/solvers/generalsolver.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
from .solver import Solver
from ..util import *
from ..util import PuzzleValue, PuzzleException
import queue as q
import progressbar

class GeneralSolver(Solver):

def __init__(self, puzzle, *args, **kwarg):
def __init__(self, puzzle):
self.remoteness = {}
self.puzzle = puzzle

def getRemoteness(self, puzzle, **kwargs):
def getRemoteness(self, puzzle):
"""Returns remoteness of puzzle. Automatically solves if memory isn't set"""
if not self.remoteness: print("Warning: No memory found. Please make sure that `solve` was called.")
if hash(puzzle) in self.remoteness: return self.remoteness[hash(puzzle)]
return PuzzleValue.UNSOLVABLE

def solve(self, *args, verbose=False, **kwargs):
def solve(self, verbose=False):
"""Traverse the entire puzzle tree and classifies all the
positions with values and remoteness
"""
Expand All @@ -27,6 +27,10 @@ def solve(self, *args, verbose=False, **kwargs):
else:
# Not a CSP - use generateSolutions()
for solution in solutions:
# Check if all the solutions are SOLVABLE
assert solution.primitive() == PuzzleValue.SOLVABLE, """
`generateSolutions` contains an UNSOLVABLE position
"""
self.remoteness[hash(solution)] = 0
queue.put(solution)

Expand All @@ -43,6 +47,9 @@ def solve(self, *args, verbose=False, **kwargs):
for move in puzzle.generateMoves('undo'):
nextPuzzle = puzzle.doMove(move)
if hash(nextPuzzle) not in self.remoteness:
assert nextPuzzle.primitive() != PuzzleValue.SOLVABLE, """
Found a state where primitive was SOLVABLE while traversing Puzzle tree
"""
self.remoteness[hash(nextPuzzle)] = self.remoteness[hash(puzzle)] + 1
queue.put(nextPuzzle)
if verbose: bar.finish()
Expand Down
2 changes: 1 addition & 1 deletion puzzlesolver/solvers/indexsolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class IndexSolver(GeneralSolver):
the index of the chunk. Recommended for puzzles with tight hash functions.
"""
def __init__(self, puzzle, *args, dir_path='databases', **kwargs):
GeneralSolver.__init__(self, puzzle, *args, **kwargs)
if not os.path.exists(dir_path): os.makedirs(dir_path)
self.path = '{}/{}.txt'.format(dir_path, puzzle.getName())
GeneralSolver.__init__(self, puzzle, *args, **kwargs)

def getRemoteness(self, puzzle, *args, **kwargs):
if hash(puzzle) in self.remoteness: return self.remoteness[hash(puzzle)]
Expand Down
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
from puzzlesolver.util import PuzzleValue
from puzzlesolver.puzzles import puzzleList, GraphPuzzle

########################################################################
# Server Fixtures
########################################################################

@pytest.fixture
def client(tmpdir):
app = server.app
Expand Down
4 changes: 2 additions & 2 deletions tests/puzzles/test_Hanoi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from puzzlesolver.puzzles import Hanoi
from puzzlesolver.solvers import GeneralSolver
from puzzlesolver.util import *
from puzzlesolver.util import PuzzleValue, PuzzleException

def move(move0, move1):
return (move0, move1)
Expand All @@ -13,7 +13,7 @@ def testHash():
"""Tests the expected behavior of the hash function on the puzzle states. """
puzzle0 = Hanoi.deserialize('3_2_1--')
puzzle1 = Hanoi.deserialize('3_2_1--')
puzzle2 = Hanoi.deserialize('-3_2_1-')
#puzzle2 = Hanoi.deserialize('-3_2_1-')
puzzle3 = Hanoi.deserialize('--3_2_1')

# Checks if two of the exact same states have the same hash
Expand Down
32 changes: 31 additions & 1 deletion tests/solvers/test_GeneralSolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,38 @@

from puzzlesolver.puzzles import GraphPuzzle
from puzzlesolver.solvers import GeneralSolver
from puzzlesolver.util import *
from puzzlesolver.util import PuzzleValue

########################################################################
# Tests
########################################################################

def testSimple(simple):
simple(GeneralSolver, csp=False)
simple(GeneralSolver, csp=True)

def testSolutionsError():
record_sol = GraphPuzzle(0, value=PuzzleValue.SOLVABLE)
missed_sol = GraphPuzzle(1, value=PuzzleValue.SOLVABLE)
not_a_solu = GraphPuzzle(2)

record_sol.setMove(missed_sol, movetype="bi")
record_sol.setMove(not_a_solu, movetype="bi")

# Two solutions, but only one is called in generateSolutions
record_sol.solutions.remove(missed_sol)

try:
solver = GeneralSolver(record_sol)
solver.solve()
except AssertionError:
pass

# generateSolutions also includes a state that is not a solution
record_sol.solutions.update(set([record_sol, missed_sol, not_a_solu]))

try:
solver = GeneralSolver(record_sol)
solver.solve()
except AssertionError:
pass

0 comments on commit 9a814d9

Please sign in to comment.