-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjarros.py
119 lines (92 loc) · 3.18 KB
/
jarros.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""
Se tienen N jarros enumerados de 1 a N, donde la capacidad en litros del jarro I es I.
Esto es, el jarro 1 tiene capacidad de 1 litro, el jarro 2, 2 litros y así
sucesivamente.
Inicialmente el jarro N está lleno de agua y los demás están vacíos.
El objetivo es que todos los jarros queden con 1 litro de agua, teniendo como
operaciones permitidas trasvasar el contenido de un jarro a otro, operación que finaliza
al llenarse el jarro de destino o vaciarse el jarro de origen.
Todo esto se tiene que lograr con el menor costo posible, siendo I el costo de trasvasar
el contenido del jarro I a otro jarro.
En este caso concreto se tienen 4 jarros.
"""
from collections import defaultdict
from simpleai.search import (
SearchProblem,
breadth_first,
depth_first,
uniform_cost,
iterative_limited_depth_first,
greedy,
astar,
)
from simpleai.search.viewers import BaseViewer
from utils import print_grid, try_search_method
VASES = 4
VASES_SIZE = (1, 2, 3, 4)
INITIAL_STATE = (0, 0, 0, 4) # liters for each vase
GOAL_STATE = (1, 1, 1, 1)
class JarrosProblem(SearchProblem):
def is_goal(self, state):
return state == GOAL_STATE
def actions(self, state):
# an action is defined by a tuple of two elements:
# (origin_vase, receiver_vase)
def is_full(vase):
return state[vase] == VASES_SIZE[vase]
vases_with_water = [
vase_position
for vase_position, vase_content in enumerate(state)
if vase_content
]
vases_not_full = [
vase_position
for vase_position, vase_content in enumerate(state)
if vase_content < VASES_SIZE[vase_position]
]
posible_actions = [
(origin_vase, receiver_vase)
for origin_vase in vases_with_water
for receiver_vase in vases_not_full
if origin_vase != receiver_vase
]
return posible_actions
def result(self, state, action):
origin_vase, receiver_vase = action
water_to_pour = min(
state[origin_vase],
VASES_SIZE[receiver_vase] - state[receiver_vase]
)
state = list(state)
state[origin_vase] -= water_to_pour
state[receiver_vase] += water_to_pour
return tuple(state)
def cost(self, state, action, state2):
return 1
def heuristic(self, state):
water_exceeded_vases = [
1
for vase_liters in state
if vase_liters > 1
]
water_missing_vases = [
1
for vase_liters in state
if vase_liters < 1
]
return max(len(water_missing_vases), len(water_exceeded_vases))
def print_state_representation(self, state):
elements = defaultdict(list)
for vase_position, vase_content in enumerate(state):
elements["X"*vase_content].append((0, vase_position))
print_grid(1, VASES, elements, VASES)
methods = (
# breadth_first,
# depth_first,
# iterative_limited_depth_first,
# uniform_cost,
greedy,
astar,
)
for search_method in methods:
try_search_method(search_method, JarrosProblem, INITIAL_STATE)