Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from .utils import pretty_matrix
- from abc import ABC, abstractmethod
- import numpy as np
- from operator import itemgetter
- from functools import total_ordering
- class State(tuple):
- __slots__ = []
- def __new__(cls, index, action, cost):
- return tuple.__new__(cls, (index,action,cost))
- index = property(itemgetter(0))
- action = property(itemgetter(1))
- cost = property(itemgetter(2))
- @staticmethod
- def initial(pos):
- """
- Return state at position pos with null value and cost
- """
- return State(pos, None, 0)
- def __repr__(self):
- return 'State(index={},action={},cost={})'.format(self.index, self.action, self.cost)
- class Actions:
- values = {
- ( 0, 0):'no',
- (-1, 0):'up',
- (-1, 1):'ur',
- ( 0, 1):'rg',
- ( 1, 1):'dr',
- ( 1, 0):'dw',
- ( 1,-1):'dl',
- ( 0,-1):'lf',
- (-1,-1):'ul',
- }
- @staticmethod
- def get(fr,to):
- diff = tuple(x-y for x,y in zip(to,fr))
- return Actions.values[diff]
- class MatrixProblem(ABC):
- @classmethod
- def parse_file(cls,filename, algorithm):
- """
- Creates MatrtixProblem object from file
- """
- with open(filename, 'r') as f:
- lines = filter(lambda x: x.strip(), f.readlines())
- mat = np.array([l.split() for l in lines])
- return cls(mat, algorithm)
- @abstractmethod
- def get_starting_states(self):
- """
- Returns the initial STATE of a problem
- """
- pass
- @abstractmethod
- def is_goal(self, state: State):
- """
- Returns wether a state is a possible ending
- """
- pass
- @abstractmethod
- def adjacent(self, state: State):
- """
- Returns the adjacent STATES to a state
- """
- pass
- @abstractmethod
- def solve(self):
- """
- Solve using algorithm
- """
- pass
- class AllyGathering(MatrixProblem):
- def __init__(self,matrix, algorithm):
- self._mat = matrix
- self._start = tuple(np.argwhere(matrix == 'R')[0])
- self._goal = tuple(np.argwhere(matrix == 'X')[0])
- self._algorithm = algorithm
- def get_starting_states(self):
- return (State.initial(self._start),)
- def is_goal(self, state):
- return self._mat[state.index] == 'X'
- def adjacent(self, state):
- pos = state.index
- x,y = pos
- idxs = filter(
- lambda a: a!=pos and self._can_move(a),
- ((x+i,y+j) for i in range(-1,2) for j in range(-1,2))
- )
- return (
- State(
- index=p,
- cost=self._cost_for_value(Actions.get(pos,p)),
- action=Actions.get(pos,p)
- ) for p in idxs
- )
- def solve(self):
- res = self._algorithm.search(self)
- return sum(s.cost for s in res.states)
- def get_goal_position(self):
- return self._goal
- def draw_path(self, path):
- n,m = self._mat.shape
- mat = self._mat.copy()
- for i,(p,_,_) in enumerate(path):
- mat[p] = i
- for i in range(n):
- for j in range(m):
- print(mat[i,j],end=' ')
- print()
- def _cost_for_value(self,value):
- if value in ('lf','rg'):
- return 5
- elif value in ('up','dw'):
- return 6
- else:
- return 10
- def __contains__(self, pos):
- x, y = pos
- n, m = self._mat.shape
- return x >= 0 and y >= 0 and x < n and y < m
- def _can_move(self, pos):
- return pos in self and self._mat[pos] != '*'
- class ConqueringProblem(MatrixProblem):
- def __init__(self,matrix, algorithm):
- self._mat = matrix
- self._enemies = np.argwhere(matrix == '.')
- self._idx_dict = {tuple(x):i for i,x in enumerate(self._enemies)}
- self._algorithm = algorithm
- def get_starting_states(self):
- """
- Returns the initial STATE of a problem
- """
- return list(self._get_border_enemies())
- def is_goal():
- raise Exception()
- def adjacent(self, state: State):
- """
- Returns the adjacent STATES to a state
- """
- x, y = self._get_idx(state.index)
- idxs = ((x+i,y+j) for i in range(-1,2) for j in range(-1,2))
- idxs = list(self._idx_dict[i] for i in idxs if i in self._idx_dict and i != (x,y))
- return idxs
- def is_enemy(self, state):
- idx = state.index
- return self._enemies
- def is_goal(self, state):
- return False
- def solve(self):
- res = self._algorithm.transverse(self)
- return self._get_output(res.states)
- ####
- def _get_output(self, enemies):
- indices = self._get_indices(enemies)
- m = self._mat.copy()
- m[indices] = 'O' # placeholder
- m[m == '.'] = 'X'
- m[m == 'O'] = '.'
- return pretty_matrix(m)
- def _get_idx(self, enemy):
- return tuple(self._enemies[enemy])
- def _get_indices(self, enemies):
- return tuple(zip(*self._enemies[enemies]))
- def _get_border_enemies(self):
- n,m = self._mat.shape
- l, r = self._enemies[:,0], self._enemies[:,1]
- return np.where((l == 0) | (r == 0) | (l == n-1) | (r == m-1))[0]
- def _in_border(self, enemy_idx):
- x, y = self._enemies[enemy_idx,:]
- n, m = self._mat.shape
- return x == 0 or y == 0 or x == n-1 or y == m-1
- def __contains__(self, idx):
- return idx in self._idx_dict
Add Comment
Please, Sign In to add comment