Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'develop'

  • Loading branch information...
commit 3c6a3d6ed6f3944ce843f6a782e7931925780817 2 parents e0d3088 + 938a08e
@fisadev fisadev authored
View
4 README.rst
@@ -91,6 +91,4 @@ Authors
* Rafael Carrascosa <rcarrascosa@machinalis.com>
* Santiago Romero <sromero@machinalis.com>
* Gonzalo García Berrotarán <ggarcia@machinalis.com>
-
-Special acknowledgements to `Machinalis <http://www.machinalis.com/>`_ for the
-time provided to work on this project.
+* Special acknowledgements to `Machinalis <http://www.machinalis.com/>`_ for the time provided to work on this project. Machinalis also works on some other very interesting projects, like `Quepy <http://quepy.machinalis.com/>`_ and `more <https://github.com/machinalis>`_.
View
101 samples/search/game_walk.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+import math
+from simpleai.search import SearchProblem, astar
+
+MAP = """
+##############################
+# # # #
+# #### ######## # #
+# o # # # #
+# ### #### ###### #
+# #### # #
+# # # # #### #
+# ###### # # x #
+# # # #
+##############################
+"""
+MAP = [list(x) for x in MAP.split("\n") if x]
+
+COSTS = {
+ "up": 1.0,
+ "down": 1.0,
+ "left": 1.0,
+ "right": 1.0,
+ "up left": 1.4,
+ "up right": 1.4,
+ "down left": 1.4,
+ "down right": 1.4,
+}
+
+
+class GameWalkPuzzle(SearchProblem):
+
+ def __init__(self, board):
+ self.board = board
+ self.goal = (0, 0)
+ for y in xrange(len(self.board)):
+ for x in xrange(len(self.board[y])):
+ if self.board[y][x].lower() == "o":
+ self.initial = (x, y)
+ elif self.board[y][x].lower() == "x":
+ self.goal = (x, y)
+
+ super(GameWalkPuzzle, self).__init__(initial_state=self.initial)
+
+ def actions(self, state):
+ actions = []
+ for action in COSTS.keys():
+ newx, newy = self.result(state, action)
+ if self.board[newy][newx] != "#":
+ actions.append(action)
+ return actions
+
+ def result(self, state, action):
+ x, y = state
+
+ if action.count("up"):
+ y -= 1
+ if action.count("down"):
+ y += 1
+ if action.count("left"):
+ x -= 1
+ if action.count("right"):
+ x += 1
+
+ new_state = (x, y)
+ return new_state
+
+ def is_goal(self, state):
+ return state == self.goal
+
+ def cost(self, state, action, state2):
+ return COSTS[action]
+
+ def heuristic(self, state):
+ x, y = state
+ gx, gy = self.goal
+ return math.sqrt((x - gx) ** 2 + (y - gy) ** 2)
+
+
+def main():
+ problem = GameWalkPuzzle(MAP)
+ result = astar(problem, graph_search=True)
+ path = [x[1] for x in result.path()]
+
+ for y in xrange(len(MAP)):
+ for x in xrange(len(MAP[y])):
+ if (x, y) == problem.initial:
+ print "o",
+ elif (x, y) == problem.goal:
+ print "x",
+ elif (x, y) in path:
+ print "·",
+ else:
+ print MAP[y][x],
+ print
+
+
+if __name__ == "__main__":
+ main()
View
2  setup.py
@@ -5,7 +5,7 @@
setup(
name='simpleai',
- version='0.5.8',
+ version='0.5.9',
description=u'An implementation of AI algorithms based on aima-python',
long_description=open('README.rst').read(),
author = u'Juan Pedro Fisanotti',
View
2  simpleai/search/__init__.py
@@ -1,5 +1,5 @@
# coding: utf-8
from simpleai.search.models import CspProblem, SearchProblem
from simpleai.search.traditional import breadth_first, depth_first, limited_depth_first, iterative_limited_depth_first, uniform_cost, greedy, astar
-from simpleai.search.local import beam, hill_climbing, hill_climbing_stochastic, simulated_annealing
+from simpleai.search.local import beam, hill_climbing, hill_climbing_stochastic, simulated_annealing, genetic, hill_climbing_random_restarts
from simpleai.search.csp import backtrack, min_conflicts, MOST_CONSTRAINED_VARIABLE, HIGHEST_DEGREE_VARIABLE, LEAST_CONSTRAINING_VALUE
View
10 simpleai/search/local.py
@@ -77,7 +77,7 @@ def _random_best_expander(fringe, iteration):
'''
current = fringe[0]
betters = [n for n in current.expand(local_search=True)
- if n.value() > current.value()]
+ if n.value > current.value]
if betters:
random.shuffle(betters)
fringe.append(betters[0])
@@ -119,7 +119,7 @@ def hill_climbing_random_restarts(problem, restarts_limit, iterations_limit=0):
fringe_size=1,
random_initial_states=True)
- if not best or best.value() < new.value():
+ if not best or best.value < new.value:
best = new
restarts += 1
@@ -146,7 +146,7 @@ def _expander(fringe, iteration):
neighbors = current.expand(local_search=True)
if neighbors:
succ = random.choice(neighbors)
- delta_e = succ.value() - current.value()
+ delta_e = succ.value - current.value
if delta_e > 0 or random.random() < math.exp(delta_e / T):
fringe.pop()
fringe.append(succ)
@@ -177,7 +177,7 @@ def _create_genetic_expander(problem, mutation_chance):
crossing over them.
'''
def _expander(fringe, iteration):
- fitness = [x.value() for x in fringe]
+ fitness = [x.value for x in fringe]
sampler = InverseTransformSampler(fitness, fringe)
new_generation = []
for _ in fringe:
@@ -243,7 +243,7 @@ def _local_search(problem, fringe_expander, iterations_limit=0, fringe_size=1,
if iterations_limit and iteration >= iterations_limit:
run = False
- elif old_best.value() >= best.value():
+ elif old_best.value >= best.value:
run = False
return best
View
21 simpleai/search/models.py
@@ -122,9 +122,6 @@ def path(self):
node = node.parent
return list(reversed(path))
- def value(self):
- return self.problem.value(self.state)
-
def __eq__(self, other):
return isinstance(other, SearchNode) and self.state == other.state
@@ -138,22 +135,28 @@ def __lt__(self, other):
class SearchNodeValueOrdered(SearchNode):
+ def __init__(self, *args, **kwargs):
+ super(SearchNodeValueOrdered, self).__init__(*args, **kwargs)
+ self.value = self.problem.value(self.state)
+
def __lt__(self, other):
# value must work inverted, because heapq sorts 1-9
# and we need 9-1 sorting
- return -self.value() < -other.value()
+ return -self.value < -other.value
class SearchNodeHeuristicOrdered(SearchNode):
+ def __init__(self, *args, **kwargs):
+ super(SearchNodeHeuristicOrdered, self).__init__(*args, **kwargs)
+ self.heuristic = self.problem.heuristic(self.state)
+
def __lt__(self, other):
- return self.problem.heuristic(self.state) < \
- self.problem.heuristic(other.state)
+ return self.heuristic < other.heuristic
-class SearchNodeStarOrdered(SearchNode):
+class SearchNodeStarOrdered(SearchNodeHeuristicOrdered):
def __lt__(self, other):
- return self.problem.heuristic(self.state) + self.cost < \
- self.problem.heuristic(other.state) + other.cost
+ return self.heuristic + self.cost < other.heuristic + other.cost
class CspProblem(object):
View
6 simpleai/search/traditional.py
@@ -115,8 +115,10 @@ def _search(problem, fringe, graph_search=False, depth_limit=None,
Basic search algorithm, base of all the other search algorithms.
'''
memory = {}
- fringe.append(node_factory(state=problem.initial_state,
- problem=problem))
+ initial_node = node_factory(state=problem.initial_state,
+ problem=problem)
+ fringe.append(initial_node)
+ memory[problem.initial_state] = initial_node
while fringe:
node = fringe.pop()
View
9 simpleai/search/utils.py
@@ -1,13 +1,14 @@
# coding=utf-8
import heapq
+from collections import deque
from itertools import izip
import random
-class FifoList(list):
- '''List that pops from the begining.'''
- def pop(self, index=0):
- return super(FifoList, self).pop(index)
+class FifoList(deque):
+ '''List that pops from the beginning.'''
+ def pop(self):
+ return super(FifoList, self).popleft()
class BoundedPriorityQueue(list):
View
4 tests/search/test_utils.py
@@ -13,9 +13,7 @@ def setUp(self):
def test_pop_returns_first_element(self):
self.assertEquals(self.f.pop(), 1)
-
- def test_pop_with_index_works(self):
- self.assertEquals(self.f.pop(1), 2)
+ self.assertEquals(len(self.f), 2)
class TestBoundedPriorityQueue(unittest.TestCase):
Please sign in to comment.
Something went wrong with that request. Please try again.