Source code for slidingpuzzle.state
# Copyright 2023 Stephen Dunn
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Provides some convience classes to track search state and results.
"""
from typing import Collection, Optional
import dataclasses
import slidingpuzzle
from slidingpuzzle.board import Board, FrozenBoard
[docs]
@dataclasses.dataclass(order=True)
class State:
"""
A dataclass for representing the state during search.
Although the ``board`` is enough to fully capture the game state,
it is convenient to track some additional information.
Args:
board: The board state.
blank_pos: The (y, x)-coord of the blank tile.
history: A list of (y, x)-coords representing moves from the initial
state to the current board state.
f: The stored value of this node. Used by some search algorithms to order
states. The value stored here has no meaning if not using a relevant
search algorithm.
g: For some search algorithms, this will hold the number of moves made to reach
this state. Used to tie-break when `f` values are identical.
"""
board: Board = dataclasses.field(compare=False)
blank_pos: tuple[int, int] = dataclasses.field(compare=False)
history: list[tuple[int, int]] = dataclasses.field(
compare=False, default_factory=list
)
f: int | float = 0
g: int = 0 # stored separately for tie-breaking
[docs]
@dataclasses.dataclass
class SearchResult:
"""
A dataclass for returning a puzzle solution along with some information
concerning how the search progressed. Useful for evaluating different
heuristics.
Args:
board: The original input board.
generated: The number of states generated during search.
expanded: The number of states evaluated during search.
unvisited: The list of states that were never reached.
visited: The set of boards evaluated.
solution: The list of moves from initial position to solution.
Note:
The ``unvisited`` and ``visited`` attributes are traditionally known
as "open" and "closed" in search parlance. However, Python's built-in
function ``open`` would collide, so they have been renamed.
"""
board: Board
generated: int
expanded: int
unvisited: Collection[State]
visited: set[FrozenBoard]
solution: Optional[list[tuple[int, int]]]
def __repr__(self) -> str:
solution = (
slidingpuzzle.solution_as_tiles(self.board, self.solution)
if self.solution
else "N/A"
)
return (
f"solution={solution}\n"
f"solution_len={len(self.solution) if self.solution else 'N/A'}, "
f"generated={self.generated}, "
f"expanded={self.expanded}, "
f"unvisited={len(self.unvisited)}, "
f"visited={len(self.visited)}"
)
def __str__(self) -> str:
return repr(self)