-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathsearch_templates.py
126 lines (102 loc) · 3.18 KB
/
search_templates.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
120
121
122
123
124
125
126
#!/usr/bin/env python3
from abc import ABC, abstractmethod
from typing import Union
class Problem(ABC):
"""Interface for search problem."""
@abstractmethod
def initial_state(self) -> object:
"""
Return the initial state of the problem.
:rtype: State
"""
pass
@abstractmethod
def actions(self, state) -> list:
"""
Return list of all available actions in a given state.
:rtype: list of Actions
"""
pass
@abstractmethod
def result(self, state, action) -> object:
"""
Return state resulting from the application of a given action in a given state.
Note: state should stay unchanged.
:rtype: State
"""
pass
@abstractmethod
def is_goal(self, state) -> bool:
"""
Return whether a given state is goal state.
"""
pass
@abstractmethod
def cost(self, state, action) -> float:
"""
Return cost of the application of a given action in a given state.
"""
pass
class HeuristicProblem(Problem):
"""Interface for heuristic problem."""
@abstractmethod
def estimate(self, state) -> float:
"""
Return estimate of the cost of the cheapest path to the goal.
"""
pass
class Optimal(ABC):
@abstractmethod
def optimal_cost(self) -> float:
"""Return cost of the optimal solution."""
pass
class Solution:
"""
Stores sequence of actions leading from some problem state
to stored goal_state
for stored path_cost
"""
def __init__(
self, actions: list, goal_state: object, path_cost: float
) -> None:
self.actions = actions
self.goal_state = goal_state
self.path_cost = path_cost
def is_valid(self, prob: Problem) -> bool:
"""
Return whether sequence of actions leads to goal_state
and whether the path_cost is correct.
"""
state = prob.initial_state()
cost = 0
for action in self.actions:
cost += prob.cost(state, action)
state = prob.result(state, action)
return (
state == self.goal_state
and prob.is_goal(state)
and cost == self.path_cost
)
def is_optimal(self, prob: Problem) -> Union[None, bool]:
"""Return whether solution is optimal (None for unknown)."""
if isinstance(prob, Optimal):
if prob.optimal_cost() == self.path_cost:
return True
else:
return False
return None
def report(self, prob: Problem) -> bool:
"""Report validity, cost and optimal cost if possible and return validity."""
if not self.is_valid(prob):
print("solution is invalid!")
return False
print("solution is valid")
print(f"total cost is {self.path_cost}")
op = self.is_optimal(prob)
if op:
print("solution is optimal")
elif op is None:
print("there is no optimal cost set for this problem")
else:
print("optimal cost is {}".format(prob.optimal_cost()))
return True