Optimization

This commit is contained in:
Lukas Wölfer
2019-04-20 02:17:08 +02:00
parent 7ebc254294
commit 90ab536240
4 changed files with 93 additions and 82 deletions

View File

@@ -1,5 +1,5 @@
"""Contains function to iterate different kinds of possible actions""" """Contains function to iterate different kinds of possible actions"""
from typing import Iterator, List from typing import Iterator, List, Tuple
from . import board from . import board
from . import board_actions from . import board_actions
@@ -168,29 +168,33 @@ def possible_field_move_actions(
"""Enumerate all possible move actions """Enumerate all possible move actions
from one field stack to another field stack""" from one field stack to another field stack"""
first_empty_field_id = -1 first_empty_field_id = -1
my_id = search_board.state_identifier cardstacks = [(index, stack)
for index, stack in enumerate(_get_cardstacks(search_board)): for index, stack in enumerate(_get_cardstacks(search_board))]
if not stack: cardstacks = [x for x in cardstacks if x[1]]
continue cardstacks = sorted(cardstacks, key=lambda x: len(x[1]))
# TODO: sort all substacks by length substacks: List[Tuple[int, List[board.Card]]] = []
for substack in (stack[i:] for i in range(len(stack))):
for index, stack in cardstacks:
substacks.extend((index, substack)
for substack in (stack[i:]
for i in range(len(stack))))
for index, substack in substacks:
for other_index, other_stack in enumerate(search_board.field): for other_index, other_stack in enumerate(search_board.field):
if index == other_index: if index == other_index:
continue continue
if other_stack: if other_stack:
if not _can_stack(other_stack[-1], substack[0]): if not _can_stack(other_stack[-1], substack[0]):
continue continue
elif len(substack) == len(search_board.field[index]):
continue
elif first_empty_field_id == -1: elif first_empty_field_id == -1:
first_empty_field_id = other_index first_empty_field_id = other_index
elif other_index != first_empty_field_id: elif other_index != first_empty_field_id:
continue continue
elif len(substack) == len(search_board.field[index]):
continue
assert search_board.state_identifier == my_id
yield board_actions.MoveAction( yield board_actions.MoveAction(
cards=substack, source_id=index, destination_id=other_index cards=substack, source_id=index, destination_id=other_index
) )
assert search_board.state_identifier == my_id
def possible_actions( def possible_actions(

View File

@@ -54,30 +54,31 @@ class SolitaireSolver:
self.stack = ActionStack() self.stack = ActionStack()
self.stack.push(self.search_board) self.stack.push(self.search_board)
def solve(self) -> List[board_actions.Action]: def solve(self) -> Iterator[List[board_actions.Action]]:
max_goal = 0
action = None
while self.stack: while self.stack:
assert (self.search_board.state_identifier == assert (self.search_board.state_identifier ==
self.stack.state_stack[-1]) self.stack.state_stack[-1])
action = self.stack.get() action = self.stack.get()
if not action: if not action:
self.stack.pop() self.stack.pop()
self.stack.action_stack[-1].undo(self.search_board) self.stack.action_stack[-1].undo(self.search_board)
assert (self.search_board.state_identifier assert (self.search_board.state_identifier
in self.state_set) in self.state_set)
continue continue
action.apply(self.search_board) action.apply(self.search_board)
if self.search_board.solved(): if self.search_board.solved():
return self.stack.action_stack yield self.stack.action_stack
if self.search_board.state_identifier in self.state_set: if self.search_board.state_identifier in self.state_set:
action.undo(self.search_board) action.undo(self.search_board)
assert self.search_board.state_identifier in self.state_set assert self.search_board.state_identifier in self.state_set
continue continue
self.state_set.add(self.search_board.state_identifier) self.state_set.add(self.search_board.state_identifier)
self.stack.push(self.search_board) self.stack.push(self.search_board)
if sum(self.search_board.goal.values()) > max_goal:
max_goal = sum(self.search_board.goal.values())
print(self.search_board.goal)
return self.stack.action_stack return self.stack.action_stack

View File

@@ -2,7 +2,8 @@
import unittest import unittest
from .context import shenzhen_solitaire from .context import shenzhen_solitaire
from shenzhen_solitaire.board import NumberCard, SpecialCard, Board from shenzhen_solitaire.board import NumberCard, SpecialCard, Board, Position
from shenzhen_solitaire.board_actions import MoveAction, BunkerizeAction, GoalAction, HuaKillAction
from shenzhen_solitaire import board_possibilities from shenzhen_solitaire import board_possibilities
from .boards import my_board from .boards import my_board
@@ -15,52 +16,57 @@ class ChainTestClass(unittest.TestCase):
self.assertTrue(my_board.check_correct()) self.assertTrue(my_board.check_correct())
sequence = [ sequence = [
0, MoveAction(
4, cards=[
0, NumberCard(
1, suit=NumberCard.Suit.Red,
0, number=7),
0, NumberCard(
8, suit=NumberCard.Suit.Green,
0, number=6)],
1, source_id=3,
3, destination_id=7),
0, BunkerizeAction(
9, card=NumberCard(
0, suit=NumberCard.Suit.Red,
2, number=6),
0, bunker_id=0,
1, field_id=2,
1, to_bunker=True),
1, GoalAction(
2, card=NumberCard(
0, suit=NumberCard.Suit.Green,
2, number=1),
1, source_id=2,
6, source_position=Position.Field),
12, MoveAction(
0, cards=[
0, NumberCard(
1, suit=NumberCard.Suit.Red,
0, number=4)],
0, source_id=2,
17, destination_id=5),
11, GoalAction(
1, card=NumberCard(
0, suit=NumberCard.Suit.Red,
0, number=1),
0, source_id=2,
0, source_position=Position.Field),
0, HuaKillAction(source_field_id=2),
0, MoveAction(
0, cards=[
0, NumberCard(
0, suit=NumberCard.Suit.Black, number=9),
0, NumberCard(suit=NumberCard.Suit.Red, number=8)],
0, source_id=6,
0, destination_id=2),
0, GoalAction(
0] card=NumberCard(
for action_index in sequence: suit=NumberCard.Suit.Green, number=2),
source_id=6,
source_position=Position.Field)
]
for action in sequence:
step = list(board_possibilities.possible_actions(my_board)) step = list(board_possibilities.possible_actions(my_board))
step[action_index].apply(my_board) self.assertIn(action, step)
action.apply(my_board)

View File

@@ -5,7 +5,7 @@ from .boards import my_board
def main() -> None: def main() -> None:
A = solver.SolitaireSolver(my_board) A = solver.SolitaireSolver(my_board)
B = A.solve() for _, B in zip(range(1), A.solve()):
print(*B, sep='\n') print(*B, sep='\n')
print(len(B)) print(len(B))