Advertisement
Guest User

Untitled

a guest
Apr 24th, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.65 KB | None | 0 0
  1. import bisect
  2. from sys import maxsize as infinity
  3.  
  4. """
  5. Дефинирање на класа за структурата на проблемот кој ќе го решаваме со пребарување.
  6. Класата Problem е апстрактна класа од која правиме наследување за дефинирање на основните
  7. карактеристики на секој проблем што сакаме да го решиме
  8. """
  9.  
  10.  
  11. class Problem:
  12. def __init__(self, initial, goal=None):
  13. self.initial = initial
  14. self.goal = goal
  15.  
  16. def successor(self, state):
  17. """За дадена состојба, врати речник од парови {акција : состојба}
  18. достапни од оваа состојба. Ако има многу следбеници, употребете
  19. итератор кој би ги генерирал следбениците еден по еден, наместо да
  20. ги генерирате сите одеднаш.
  21.  
  22. :param state: дадена состојба
  23. :return: речник од парови {акција : состојба} достапни од оваа
  24. состојба
  25. :rtype: dict
  26. """
  27. raise NotImplementedError
  28.  
  29. def actions(self, state):
  30. """За дадена состојба state, врати листа од сите акции што може да
  31. се применат над таа состојба
  32.  
  33. :param state: дадена состојба
  34. :return: листа на акции
  35. :rtype: list
  36. """
  37. return self.successor(state).keys()
  38.  
  39. def result(self, state, action):
  40. """За дадена состојба state и акција action, врати ја состојбата
  41. што се добива со примена на акцијата над состојбата
  42.  
  43. :param state: дадена состојба
  44. :param action: дадена акција
  45. :return: резултантна состојба
  46. """
  47. possible = self.successor(state)
  48. return possible[action]
  49.  
  50.  
  51. def goal_test(self, state):
  52. """Врати True ако state е целна состојба. Даденава имплементација
  53. на методот директно ја споредува state со self.goal, како што е
  54. специфицирана во конструкторот. Имплементирајте го овој метод ако
  55. проверката со една целна состојба self.goal не е доволна.
  56.  
  57. :param state: дадена состојба
  58. :return: дали дадената состојба е целна состојба
  59. :rtype: bool
  60. """
  61. return state == self.goal
  62.  
  63. def path_cost(self, c, state1, action, state2):
  64. """Врати ја цената на решавачкиот пат кој пристигнува во состојбата
  65. state2 од состојбата state1 преку акцијата action, претпоставувајќи
  66. дека цената на патот до состојбата state1 е c. Ако проблемот е таков
  67. што патот не е важен, оваа функција ќе ја разгледува само состојбата
  68. state2. Ако патот е важен, ќе ја разгледува цената c и можеби и
  69. state1 и action. Даденава имплементација му доделува цена 1 на секој
  70. чекор од патот.
  71.  
  72. :param c: цена на патот до состојбата state1
  73. :param state1: дадена моментална состојба
  74. :param action: акција која треба да се изврши
  75. :param state2: состојба во која треба да се стигне
  76. :return: цена на патот по извршување на акцијата
  77. :rtype: float
  78. """
  79. return c + 1
  80.  
  81. def value(self):
  82. """За проблеми на оптимизација, секоја состојба си има вредност. 
  83. Hill-climbing и сличните алгоритми се обидуваат да ја максимизираат
  84. оваа вредност.
  85.  
  86. :return: вредност на состојба
  87. :rtype: float
  88. """
  89. raise NotImplementedError
  90.  
  91.  
  92. """
  93. Дефинирање на класата за структурата на јазел од пребарување.
  94. Класата Node не се наследува
  95. """
  96.  
  97.  
  98. class Node:
  99. def __init__(self, state, parent=None, action=None, path_cost=0):
  100. """Креирај јазол од пребарувачкото дрво, добиен од parent со примена
  101. на акцијата action
  102.  
  103. :param state: моментална состојба (current state)
  104. :param parent: родителска состојба (parent state)
  105. :param action: акција (action)
  106. :param path_cost: цена на патот (path cost)
  107. """
  108. self.state = state
  109. self.parent = parent
  110. self.action = action
  111. self.path_cost = path_cost
  112. self.depth = 0 # search depth
  113. if parent:
  114. self.depth = parent.depth + 1
  115.  
  116. def __repr__(self):
  117. return "<Node %s>" % (self.state,)
  118.  
  119. def __lt__(self, node):
  120. return self.state < node.state
  121.  
  122. def expand(self, problem):
  123. """Излистај ги јазлите достапни во еден чекор од овој јазол.
  124.  
  125. :param problem: даден проблем
  126. :return: листа на достапни јазли во еден чекор
  127. :rtype: list(Node)
  128. """
  129. return [self.child_node(problem, action)
  130. for action in problem.actions(self.state)]
  131.  
  132. def child_node(self, problem, action):
  133. """Дете јазел
  134.  
  135. :param problem: даден проблем
  136. :param action: дадена акција
  137. :return: достапен јазел според дадената акција
  138. :rtype: Node
  139. """
  140. next_state = problem.result(self.state, action)
  141. return Node(next_state, self, action,
  142. problem.path_cost(self.path_cost, self.state,
  143. action, next_state))
  144.  
  145. def solution(self):
  146. """Врати ја секвенцата од акции за да се стигне од коренот до овој јазол.
  147.  
  148. :return: секвенцата од акции
  149. :rtype: list
  150. """
  151. return [node.action for node in self.path()[1:]]
  152.  
  153. def solve(self):
  154. """Врати ја секвенцата од состојби за да се стигне од коренот до овој јазол.
  155.  
  156. :return: листа од состојби
  157. :rtype: list
  158. """
  159. return [node.state for node in self.path()[0:]]
  160.  
  161. def path(self):
  162. """Врати ја листата од јазли што го формираат патот од коренот до овој јазол.
  163.  
  164. :return: листа од јазли од патот
  165. :rtype: list(Node)
  166. """
  167. x, result = self, []
  168. while x:
  169. result.append(x)
  170. x = x.parent
  171. result.reverse()
  172. return result
  173.  
  174. """Сакаме редицата од јазли кај breadth_first_search или
  175. astar_search да не содржи состојби - дупликати, па јазлите што
  176. содржат иста состојба ги третираме како исти. [Проблем: ова може
  177. да не биде пожелно во други ситуации.]"""
  178.  
  179. def __eq__(self, other):
  180. return isinstance(other, Node) and self.state == other.state
  181.  
  182. def __hash__(self):
  183. return hash(self.state)
  184.  
  185.  
  186. """
  187. Дефинирање на помошни структури за чување на листата на генерирани, но непроверени јазли
  188. """
  189.  
  190.  
  191. class Queue:
  192. """Queue е апстрактна класа / интерфејс. Постојат 3 типа:
  193.         Stack(): Last In First Out Queue (стек).
  194.         FIFOQueue(): First In First Out Queue (редица).
  195.         PriorityQueue(order, f): Queue во сортиран редослед (подразбирливо,од најмалиот кон
  196. најголемиот јазол).
  197.     """
  198.  
  199. def __init__(self):
  200. raise NotImplementedError
  201.  
  202. def append(self, item):
  203. """Додади го елементот item во редицата
  204.  
  205. :param item: даден елемент
  206. :return: None
  207. """
  208. raise NotImplementedError
  209.  
  210. def extend(self, items):
  211. """Додади ги елементите items во редицата
  212.  
  213. :param items: дадени елементи
  214. :return: None
  215. """
  216. raise NotImplementedError
  217.  
  218. def pop(self):
  219. """Врати го првиот елемент од редицата
  220.  
  221. :return: прв елемент
  222. """
  223. raise NotImplementedError
  224.  
  225. def __len__(self):
  226. """Врати го бројот на елементи во редицата
  227.  
  228. :return: број на елементи во редицата
  229. :rtype: int
  230. """
  231. raise NotImplementedError
  232.  
  233. def __contains__(self, item):
  234. """Проверка дали редицата го содржи елементот item
  235.  
  236. :param item: даден елемент
  237. :return: дали queue го содржи item
  238. :rtype: bool
  239. """
  240. raise NotImplementedError
  241.  
  242.  
  243. class Stack(Queue):
  244. """Last-In-First-Out Queue."""
  245.  
  246. def __init__(self):
  247. self.data = []
  248.  
  249. def append(self, item):
  250. self.data.append(item)
  251.  
  252. def extend(self, items):
  253. self.data.extend(items)
  254.  
  255. def pop(self):
  256. return self.data.pop()
  257.  
  258. def __len__(self):
  259. return len(self.data)
  260.  
  261. def __contains__(self, item):
  262. return item in self.data
  263.  
  264.  
  265. class FIFOQueue(Queue):
  266. """First-In-First-Out Queue."""
  267.  
  268. def __init__(self):
  269. self.data = []
  270.  
  271. def append(self, item):
  272. self.data.append(item)
  273.  
  274. def extend(self, items):
  275. self.data.extend(items)
  276.  
  277. def pop(self):
  278. return self.data.pop(0)
  279.  
  280. def __len__(self):
  281. return len(self.data)
  282.  
  283. def __contains__(self, item):
  284. return item in self.data
  285.  
  286.  
  287. class PriorityQueue(Queue):
  288. """Редица во која прво се враќа минималниот (или максималниот) елемент
  289. (како што е определено со f и order). Оваа структура се користи кај
  290. информирано пребарување"""
  291. """"""
  292.  
  293. def __init__(self, order=min, f=lambda x: x):
  294. """
  295. :param order: функција за подредување, ако order е min, се враќа елементот
  296. со минимална f(x); ако order е max, тогаш се враќа елементот
  297. со максимална f(x).
  298. :param f: функција f(x)
  299. """
  300. assert order in [min, max]
  301. self.data = []
  302. self.order = order
  303. self.f = f
  304.  
  305. def append(self, item):
  306. bisect.insort_right(self.data, (self.f(item), item))
  307.  
  308. def extend(self, items):
  309. for item in items:
  310. bisect.insort_right(self.data, (self.f(item), item))
  311.  
  312. def pop(self):
  313. if self.order == min:
  314. return self.data.pop(0)[1]
  315. return self.data.pop()[1]
  316.  
  317. def __len__(self):
  318. return len(self.data)
  319.  
  320. def __contains__(self, item):
  321. return any(item == pair[1] for pair in self.data)
  322.  
  323. def __getitem__(self, key):
  324. for _, item in self.data:
  325. if item == key:
  326. return item
  327.  
  328. def __delitem__(self, key):
  329. for i, (value, item) in enumerate(self.data):
  330. if item == key:
  331. self.data.pop(i)
  332.  
  333.  
  334. """
  335. Информирано пребарување во рамки на граф
  336. """
  337.  
  338.  
  339. def memoize(fn, slot=None):
  340. """ Запамети ја пресметаната вредност за која била листа од
  341. аргументи. Ако е специфициран slot, зачувај го резултатот во
  342. тој slot на првиот аргумент. Ако slot е None, зачувај ги
  343. резултатите во речник.
  344.  
  345. :param fn: зададена функција
  346. :param slot: име на атрибут во кој се чуваат резултатите од функцијата
  347. :return: функција со модификација за зачувување на резултатите
  348. """
  349. if slot:
  350. def memoized_fn(obj, *args):
  351. if hasattr(obj, slot):
  352. return getattr(obj, slot)
  353. else:
  354. val = fn(obj, *args)
  355. setattr(obj, slot, val)
  356. return val
  357. else:
  358. def memoized_fn(*args):
  359. if args not in memoized_fn.cache:
  360. memoized_fn.cache[args] = fn(*args)
  361. return memoized_fn.cache[args]
  362.  
  363. memoized_fn.cache = {}
  364. return memoized_fn
  365.  
  366.  
  367. def best_first_graph_search(problem, f):
  368. """Пребарувај низ следбениците на даден проблем за да најдеш цел. Користи
  369. функција за евалуација за да се одлучи кој е сосед најмногу ветува и
  370. потоа да се истражи. Ако до дадена состојба стигнат два пата, употреби
  371. го најдобриот пат.
  372.  
  373. :param problem: даден проблем
  374. :param f: дадена функција за евристика
  375. :return: Node or None
  376. """
  377. f = memoize(f, 'f')
  378. node = Node(problem.initial)
  379. if problem.goal_test(node.state):
  380. return node
  381. frontier = PriorityQueue(min, f)
  382. frontier.append(node)
  383. explored = set()
  384. while frontier:
  385. node = frontier.pop()
  386. if problem.goal_test(node.state):
  387. return node
  388. explored.add(node.state)
  389. for child in node.expand(problem):
  390. if child.state not in explored and child not in frontier:
  391. frontier.append(child)
  392. elif child in frontier:
  393. incumbent = frontier[child]
  394. if f(child) < f(incumbent):
  395. del frontier[incumbent]
  396. frontier.append(child)
  397. return None
  398.  
  399.  
  400. def greedy_best_first_graph_search(problem, h=None):
  401. """ Greedy best-first пребарување се остварува ако се специфицира дека f(n) = h(n).
  402.  
  403. :param problem: даден проблем
  404. :param h: дадена функција за евристика
  405. :return: Node or None
  406. """
  407. h = memoize(h or problem.h, 'h')
  408. return best_first_graph_search(problem, h)
  409.  
  410.  
  411. def astar_search(problem, h=None):
  412. """ A* пребарување е best-first graph пребарување каде f(n) = g(n) + h(n).
  413.  
  414. :param problem: даден проблем
  415. :param h: дадена функција за евристика
  416. :return: Node or None
  417. """
  418. h = memoize(h or problem.h, 'h')
  419. return best_first_graph_search(problem, lambda n: n.path_cost + h(n))
  420.  
  421.  
  422. def recursive_best_first_search(problem, h=None):
  423. """Recursive best first search - ја ограничува рекурзијата
  424. преку следење на f-вредноста на најдобриот алтернативен пат
  425. од било кој јазел предок (еден чекор гледање нанапред).
  426.  
  427. :param problem: даден проблем
  428. :param h: дадена функција за евристика
  429. :return: Node or None
  430. """
  431. h = memoize(h or problem.h, 'h')
  432.  
  433. def RBFS(problem, node, flimit):
  434. if problem.goal_test(node.state):
  435. return node, 0 # (втората вредност е неважна)
  436. successors = node.expand(problem)
  437. if len(successors) == 0:
  438. return None, infinity
  439. for s in successors:
  440. s.f = max(s.path_cost + h(s), node.f)
  441. while True:
  442. # Подреди ги според најниската f вредност
  443. successors.sort(key=lambda x: x.f)
  444. best = successors[0]
  445. if best.f > flimit:
  446. return None, best.f
  447. if len(successors) > 1:
  448. alternative = successors[1].f
  449. else:
  450. alternative = infinity
  451. result, best.f = RBFS(problem, best, min(flimit, alternative))
  452. if result is not None:
  453. return result, best.f
  454.  
  455. node = Node(problem.initial)
  456. node.f = h(node)
  457. result, bestf = RBFS(problem, node, infinity)
  458. return result
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473. def UpdateObsticle1(currentState):
  474. redica = currentState[0]
  475. kolona = currentState[1]
  476. pravec = currentState[2]
  477.  
  478. if kolona == 0:
  479. pravec = 1
  480. elif kolona == 4:
  481. pravec = -1
  482.  
  483. if pravec == 1:
  484. kolona = kolona + 1
  485.  
  486. elif pravec == -1:
  487. kolona = kolona - 1
  488. return (redica,kolona,pravec)
  489.  
  490. def UpdateObsticle2(currentState):
  491. redica = currentState[0]
  492. kolona = currentState[1]
  493. pravec = currentState[2]
  494.  
  495. if kolona == 4:
  496. pravec = -1
  497. elif kolona == 0:
  498. pravec = 1
  499.  
  500. if pravec == 1:
  501. kolona = kolona + 1
  502. redica = redica - 1
  503. elif pravec == -1:
  504. kolona = kolona - 1
  505. redica = redica + 1
  506. return (redica,kolona,pravec)
  507.  
  508.  
  509. def UpdateObsticle3(currentState):
  510. redica = currentState[0]
  511. kolona = currentState[1]
  512. pravec = currentState[2]
  513.  
  514. if redica == 5:
  515. pravec = -1
  516. elif redica == 9:
  517. pravec = 1
  518. if pravec == 1:
  519. redica = redica - 1
  520. elif pravec == -1:
  521. redica = redica + 1
  522. return (redica,kolona,pravec)
  523.  
  524.  
  525.  
  526. def isValid(coveceRedica,coveceKolona,precka1,precka2,precka3):
  527.  
  528. if (coveceRedica == precka1[0] and (coveceKolona == precka1[1] or coveceKolona == precka1[1]+1)):
  529. return False
  530. if ((coveceRedica == precka2[0] or coveceRedica == precka2[0]+1) and (coveceKolona==precka2[1] or coveceKolona == precka2[1]+1)):
  531. return False
  532. if ((coveceRedica == precka3[0] or coveceRedica == precka3[0]+1) and (coveceKolona == precka3[1])):
  533. return False
  534. return True
  535.  
  536.  
  537.  
  538. import bisect
  539.  
  540.  
  541. """
  542. Дефинирање на класа за структурата на проблемот кој ќе го решаваме со пребарување.
  543. Класата Problem е апстрактна класа од која правиме наследување за дефинирање на основните
  544. карактеристики на секој проблем што сакаме да го решиме
  545. """
  546.  
  547.  
  548. class Problem:
  549. def __init__(self, initial, goal=None):
  550. self.initial = initial
  551. self.goal = goal
  552.  
  553. def successor(self, state):
  554. """За дадена состојба, врати речник од парови {акција : состојба}
  555. достапни од оваа состојба. Ако има многу следбеници, употребете
  556. итератор кој би ги генерирал следбениците еден по еден, наместо да
  557. ги генерирате сите одеднаш.
  558.  
  559. :param state: дадена состојба
  560. :return: речник од парови {акција : состојба} достапни од оваа
  561. состојба
  562. :rtype: dict
  563. """
  564. raise NotImplementedError
  565.  
  566. def actions(self, state):
  567. """За дадена состојба state, врати листа од сите акции што може да
  568. се применат над таа состојба
  569.  
  570. :param state: дадена состојба
  571. :return: листа на акции
  572. :rtype: list
  573. """
  574. return self.successor(state).keys()
  575.  
  576. def result(self, state, action):
  577. """За дадена состојба state и акција action, врати ја состојбата
  578. што се добива со примена на акцијата над состојбата
  579.  
  580. :param state: дадена состојба
  581. :param action: дадена акција
  582. :return: резултантна состојба
  583. """
  584. possible = self.successor(state)
  585. return possible[action]
  586.  
  587.  
  588. def goal_test(self, state):
  589. """Врати True ако state е целна состојба. Даденава имплементација
  590. на методот директно ја споредува state со self.goal, како што е
  591. специфицирана во конструкторот. Имплементирајте го овој метод ако
  592. проверката со една целна состојба self.goal не е доволна.
  593.  
  594. :param state: дадена состојба
  595. :return: дали дадената состојба е целна состојба
  596. :rtype: bool
  597. """
  598. return state == self.goal
  599.  
  600. def path_cost(self, c, state1, action, state2):
  601. """Врати ја цената на решавачкиот пат кој пристигнува во состојбата
  602. state2 од состојбата state1 преку акцијата action, претпоставувајќи
  603. дека цената на патот до состојбата state1 е c. Ако проблемот е таков
  604. што патот не е важен, оваа функција ќе ја разгледува само состојбата
  605. state2. Ако патот е важен, ќе ја разгледува цената c и можеби и
  606. state1 и action. Даденава имплементација му доделува цена 1 на секој
  607. чекор од патот.
  608.  
  609. :param c: цена на патот до состојбата state1
  610. :param state1: дадена моментална состојба
  611. :param action: акција која треба да се изврши
  612. :param state2: состојба во која треба да се стигне
  613. :return: цена на патот по извршување на акцијата
  614. :rtype: float
  615. """
  616. return c + 1
  617.  
  618. def value(self):
  619. """За проблеми на оптимизација, секоја состојба си има вредност. 
  620. Hill-climbing и сличните алгоритми се обидуваат да ја максимизираат
  621. оваа вредност.
  622.  
  623. :return: вредност на состојба
  624. :rtype: float
  625. """
  626. raise NotImplementedError
  627.  
  628.  
  629. """
  630. Дефинирање на класата за структурата на јазел од пребарување.
  631. Класата Node не се наследува
  632. """
  633.  
  634.  
  635. class Node:
  636. def __init__(self, state, parent=None, action=None, path_cost=0):
  637. """Креирај јазол од пребарувачкото дрво, добиен од parent со примена
  638. на акцијата action
  639.  
  640. :param state: моментална состојба (current state)
  641. :param parent: родителска состојба (parent state)
  642. :param action: акција (action)
  643. :param path_cost: цена на патот (path cost)
  644. """
  645. self.state = state
  646. self.parent = parent
  647. self.action = action
  648. self.path_cost = path_cost
  649. self.depth = 0 # search depth
  650. if parent:
  651. self.depth = parent.depth + 1
  652.  
  653. def __repr__(self):
  654. return "<Node %s>" % (self.state,)
  655.  
  656. def __lt__(self, node):
  657. return self.state < node.state
  658.  
  659. def expand(self, problem):
  660. """Излистај ги јазлите достапни во еден чекор од овој јазол.
  661.  
  662. :param problem: даден проблем
  663. :return: листа на достапни јазли во еден чекор
  664. :rtype: list(Node)
  665. """
  666. return [self.child_node(problem, action)
  667. for action in problem.actions(self.state)]
  668.  
  669. def child_node(self, problem, action):
  670. """Дете јазел
  671.  
  672. :param problem: даден проблем
  673. :param action: дадена акција
  674. :return: достапен јазел според дадената акција
  675. :rtype: Node
  676. """
  677. next_state = problem.result(self.state, action)
  678. return Node(next_state, self, action,
  679. problem.path_cost(self.path_cost, self.state,
  680. action, next_state))
  681.  
  682. def solution(self):
  683. """Врати ја секвенцата од акции за да се стигне од коренот до овој јазол.
  684.  
  685. :return: секвенцата од акции
  686. :rtype: list
  687. """
  688. return [node.action for node in self.path()[1:]]
  689.  
  690. def solve(self):
  691. """Врати ја секвенцата од состојби за да се стигне од коренот до овој јазол.
  692.  
  693. :return: листа од состојби
  694. :rtype: list
  695. """
  696. return [node.state for node in self.path()[0:]]
  697.  
  698. def path(self):
  699. """Врати ја листата од јазли што го формираат патот од коренот до овој јазол.
  700.  
  701. :return: листа од јазли од патот
  702. :rtype: list(Node)
  703. """
  704. x, result = self, []
  705. while x:
  706. result.append(x)
  707. x = x.parent
  708. result.reverse()
  709. return result
  710.  
  711. """Сакаме редицата од јазли кај breadth_first_search или
  712. astar_search да не содржи состојби - дупликати, па јазлите што
  713. содржат иста состојба ги третираме како исти. [Проблем: ова може
  714. да не биде пожелно во други ситуации.]"""
  715.  
  716. def __eq__(self, other):
  717. return isinstance(other, Node) and self.state == other.state
  718.  
  719. def __hash__(self):
  720. return hash(self.state)
  721.  
  722.  
  723. """
  724. Дефинирање на помошни структури за чување на листата на генерирани, но непроверени јазли
  725. """
  726.  
  727.  
  728. class Queue:
  729. """Queue е апстрактна класа / интерфејс. Постојат 3 типа:
  730.         Stack(): Last In First Out Queue (стек).
  731.         FIFOQueue(): First In First Out Queue (редица).
  732.         PriorityQueue(order, f): Queue во сортиран редослед (подразбирливо,од најмалиот кон
  733. најголемиот јазол).
  734.     """
  735.  
  736. def __init__(self):
  737. raise NotImplementedError
  738.  
  739. def append(self, item):
  740. """Додади го елементот item во редицата
  741.  
  742. :param item: даден елемент
  743. :return: None
  744. """
  745. raise NotImplementedError
  746.  
  747. def extend(self, items):
  748. """Додади ги елементите items во редицата
  749.  
  750. :param items: дадени елементи
  751. :return: None
  752. """
  753. raise NotImplementedError
  754.  
  755. def pop(self):
  756. """Врати го првиот елемент од редицата
  757.  
  758. :return: прв елемент
  759. """
  760. raise NotImplementedError
  761.  
  762. def __len__(self):
  763. """Врати го бројот на елементи во редицата
  764.  
  765. :return: број на елементи во редицата
  766. :rtype: int
  767. """
  768. raise NotImplementedError
  769.  
  770. def __contains__(self, item):
  771. """Проверка дали редицата го содржи елементот item
  772.  
  773. :param item: даден елемент
  774. :return: дали queue го содржи item
  775. :rtype: bool
  776. """
  777. raise NotImplementedError
  778.  
  779.  
  780. class Stack(Queue):
  781. """Last-In-First-Out Queue."""
  782.  
  783. def __init__(self):
  784. self.data = []
  785.  
  786. def append(self, item):
  787. self.data.append(item)
  788.  
  789. def extend(self, items):
  790. self.data.extend(items)
  791.  
  792. def pop(self):
  793. return self.data.pop()
  794.  
  795. def __len__(self):
  796. return len(self.data)
  797.  
  798. def __contains__(self, item):
  799. return item in self.data
  800.  
  801.  
  802. class FIFOQueue(Queue):
  803. """First-In-First-Out Queue."""
  804.  
  805. def __init__(self):
  806. self.data = []
  807.  
  808. def append(self, item):
  809. self.data.append(item)
  810.  
  811. def extend(self, items):
  812. self.data.extend(items)
  813.  
  814. def pop(self):
  815. return self.data.pop(0)
  816.  
  817. def __len__(self):
  818. return len(self.data)
  819.  
  820. def __contains__(self, item):
  821. return item in self.data
  822.  
  823.  
  824. class PriorityQueue(Queue):
  825. """Редица во која прво се враќа минималниот (или максималниот) елемент
  826. (како што е определено со f и order). Оваа структура се користи кај
  827. информирано пребарување"""
  828. """"""
  829.  
  830. def __init__(self, order=min, f=lambda x: x):
  831. """
  832. :param order: функција за подредување, ако order е min, се враќа елементот
  833. со минимална f(x); ако order е max, тогаш се враќа елементот
  834. со максимална f(x).
  835. :param f: функција f(x)
  836. """
  837. assert order in [min, max]
  838. self.data = []
  839. self.order = order
  840. self.f = f
  841.  
  842. def append(self, item):
  843. bisect.insort_right(self.data, (self.f(item), item))
  844.  
  845. def extend(self, items):
  846. for item in items:
  847. bisect.insort_right(self.data, (self.f(item), item))
  848.  
  849. def pop(self):
  850. if self.order == min:
  851. return self.data.pop(0)[1]
  852. return self.data.pop()[1]
  853.  
  854. def __len__(self):
  855. return len(self.data)
  856.  
  857. def __contains__(self, item):
  858. return any(item == pair[1] for pair in self.data)
  859.  
  860. def __getitem__(self, key):
  861. for _, item in self.data:
  862. if item == key:
  863. return item
  864.  
  865. def __delitem__(self, key):
  866. for i, (value, item) in enumerate(self.data):
  867. if item == key:
  868. self.data.pop(i)
  869.  
  870. class CrnoBelo(Problem):
  871. def __init__(self, initial, goal, n):
  872. super().__init__(initial, goal)
  873. self.n = n
  874.  
  875. def goal_test(self, state):
  876. counter = 0
  877. for i in range(0, len(state)):
  878. if state[i] == goal[i]:
  879. counter += 1
  880. return counter == len(state)
  881.  
  882. def successor(self, state):
  883. successors = dict()
  884. for i in range(0, len(state)):
  885. x = i // n
  886. y = i % n
  887. koord = 'x: ' + str(x) + ', y: ' + str(y)
  888. new_state = list(state)
  889.  
  890. #Samoto pole
  891. if state[i] == 0:
  892. new_state[i] = 1
  893. else:
  894. new_state[i] = 0
  895.  
  896. #Poleto nad momentalnoto
  897. if i > n-1:
  898. if state[i-n] == 0:
  899. new_state[i-n] = 1
  900. else:
  901. new_state[i-n] = 0
  902.  
  903. #Poleto pod momentalnoto
  904. if i < n*n-n:
  905. if state[i+n] == 0:
  906. new_state[i+n] = 1
  907. else:
  908. new_state[i+n] = 0
  909.  
  910. #Poleto levo od momentalnoto
  911. if i % n > 0:
  912. if state[i-1] == 0:
  913. new_state[i-1] = 1
  914. else:
  915. new_state[i-1] = 0
  916.  
  917. #Poleto desno od momentalnoto
  918. if i % n < n-1:
  919. if state[i+1] == 0:
  920. new_state[i+1] = 1
  921. else:
  922. new_state[i+1] = 0
  923.  
  924. successors[koord] = tuple(new_state)
  925.  
  926. return successors
  927. def h(self, node):
  928. counter = 0
  929. for zero in node.state:
  930. if zero == 0:
  931. counter += 1
  932. return counter
  933.  
  934.  
  935. def actions(self, state):
  936. return self.successor(state).keys()
  937.  
  938. def result(self, state, action):
  939. possible = self.successor(state)
  940. return possible[action]
  941.  
  942.  
  943. """
  944. Неинформирано пребарување во рамки на дрво.
  945. Во рамки на дрвото не разрешуваме јамки.
  946. """
  947.  
  948.  
  949. def tree_search(problem, fringe):
  950. """ Пребарувај низ следбениците на даден проблем за да најдеш цел.
  951.  
  952. :param problem: даден проблем
  953. :param fringe: празна редица (queue)
  954. :return: Node
  955. """
  956. fringe.append(Node(problem.initial))
  957. while fringe:
  958. node = fringe.pop()
  959. print(node.state)
  960. if problem.goal_test(node.state):
  961. return node
  962. fringe.extend(node.expand(problem))
  963. return None
  964.  
  965.  
  966. def breadth_first_tree_search(problem):
  967. """Експандирај го прво најплиткиот јазол во пребарувачкото дрво.
  968.  
  969. :param problem: даден проблем
  970. :return: Node
  971. """
  972. return tree_search(problem, FIFOQueue())
  973.  
  974.  
  975. def depth_first_tree_search(problem):
  976. """Експандирај го прво најдлабокиот јазол во пребарувачкото дрво.
  977.  
  978. :param problem:даден проблем
  979. :return: Node
  980. """
  981. return tree_search(problem, Stack())
  982.  
  983.  
  984. """
  985. Неинформирано пребарување во рамки на граф
  986. Основната разлика е во тоа што овде не дозволуваме јамки,
  987. т.е. повторување на состојби
  988. """
  989.  
  990.  
  991. def graph_search(problem, fringe):
  992. """Пребарувај низ следбениците на даден проблем за да најдеш цел.
  993. Ако до дадена состојба стигнат два пата, употреби го најдобриот пат.
  994.  
  995. :param problem: даден проблем
  996. :param fringe: празна редица (queue)
  997. :return: Node
  998. """
  999. closed = {}
  1000. fringe.append(Node(problem.initial))
  1001. while fringe:
  1002. node = fringe.pop()
  1003. if problem.goal_test(node.state):
  1004. return node
  1005. if node.state not in closed:
  1006. closed[node.state] = True
  1007. fringe.extend(node.expand(problem))
  1008. return None
  1009.  
  1010.  
  1011. def breadth_first_graph_search(problem):
  1012. """Експандирај го прво најплиткиот јазол во пребарувачкиот граф.
  1013.  
  1014. :param problem: даден проблем
  1015. :return: Node
  1016. """
  1017. return graph_search(problem, FIFOQueue())
  1018.  
  1019.  
  1020. def depth_first_graph_search(problem):
  1021. """Експандирај го прво најдлабокиот јазол во пребарувачкиот граф.
  1022.  
  1023. :param problem: даден проблем
  1024. :return: Node
  1025. """
  1026. return graph_search(problem, Stack())
  1027.  
  1028.  
  1029. def depth_limited_search(problem, limit=50):
  1030. def recursive_dls(node, problem, limit):
  1031. """Помошна функција за depth limited"""
  1032. cutoff_occurred = False
  1033. if problem.goal_test(node.state):
  1034. return node
  1035. elif node.depth == limit:
  1036. return 'cutoff'
  1037. else:
  1038. for successor in node.expand(problem):
  1039. result = recursive_dls(successor, problem, limit)
  1040. if result == 'cutoff':
  1041. cutoff_occurred = True
  1042. elif result is not None:
  1043. return result
  1044. if cutoff_occurred:
  1045. return 'cutoff'
  1046. return None
  1047.  
  1048. return recursive_dls(Node(problem.initial), problem, limit)
  1049.  
  1050.  
  1051. def iterative_deepening_search(problem):
  1052. for depth in range(sys.maxsize):
  1053. result = depth_limited_search(problem, depth)
  1054. if result is not 'cutoff':
  1055. return result
  1056.  
  1057.  
  1058. def uniform_cost_search(problem):
  1059. """Експандирај го прво јазолот со најниска цена во пребарувачкиот граф."""
  1060. return graph_search(problem, PriorityQueue(lambda a, b:
  1061. a.path_cost < b.path_cost))
  1062.  
  1063. class CrnoBelo(Problem):
  1064. def __init__(self, initial, goal, n):
  1065. super().__init__(initial, goal)
  1066. self.n = n
  1067.  
  1068. def goal_test(self, state):
  1069. counter = 0
  1070. for i in range(0, len(state)):
  1071. if state[i] == goal[i]:
  1072. counter += 1
  1073. return counter == len(state)
  1074.  
  1075. def successor(self, state):
  1076. successors = dict()
  1077. for i in range(0, len(state)):
  1078. x = i // n
  1079. y = i % n
  1080. koord = 'x: ' + str(x) + ', y: ' + str(y)
  1081. new_state = list(state)
  1082.  
  1083. #Samoto pole
  1084. if state[i] == 0:
  1085. new_state[i] = 1
  1086. else:
  1087. new_state[i] = 0
  1088.  
  1089. #Poleto nad momentalnoto
  1090. if i > n-1:
  1091. for m in range(n,1000,n):
  1092. if i>m-1: break
  1093.  
  1094. if state[i-m] == 0:
  1095. new_state[i-m] = 1
  1096. else:
  1097. new_state[i-m] = 0
  1098.  
  1099. #Poleto pod momentalnoto
  1100. if i < n*n-n:
  1101. for m in range(n, 1000, n):
  1102. if i < m * m - m: break
  1103. if state[i+m] == 0:
  1104. new_state[i+m] = 1
  1105. else:
  1106. new_state[i+m] = 0
  1107.  
  1108. #Poleto levo od momentalnoto
  1109. if i % n > 0:
  1110. for m in range(n, 1000, n):
  1111. if i % m > 0: break
  1112. if state[i-1] == 0:
  1113. new_state[i-1] = 1
  1114. else:
  1115. new_state[i-1] = 0
  1116.  
  1117. #Poleto desno od momentalnoto
  1118. if i % n < n-1:
  1119. for m in range(n, 1000, n):
  1120. if i % m < m - 1: break
  1121. if state[i+1] == 0:
  1122. new_state[i+1] = 1
  1123. else:
  1124. new_state[i+1] = 0
  1125.  
  1126. successors[koord] = tuple(new_state)
  1127.  
  1128. return successors
  1129. def h(self, node):
  1130. counter = 0
  1131. for zero in node.state:
  1132. if zero == 0:
  1133. counter += 1
  1134. return counter
  1135.  
  1136.  
  1137. def actions(self, state):
  1138. return self.successor(state).keys()
  1139.  
  1140. def result(self, state, action):
  1141. possible = self.successor(state)
  1142. return possible[action]
  1143. def h(self,node):
  1144. counter=0
  1145. for i in range(0,len(node.state)):
  1146. if node.state[i] == 0:
  1147. counter=counter+1
  1148. return counter
  1149.  
  1150. if __name__ == '__main__':
  1151. # Vcituvanje na vleznite argumenti za test primerite
  1152.  
  1153. n = int(input())
  1154. polinja = list(map(int, input().split(',')))
  1155.  
  1156. # Vasiot kod pisuvajte go pod ovoj komentar
  1157.  
  1158. goal = []
  1159.  
  1160. for i in range(0, n * n):
  1161. goal.append(1)
  1162.  
  1163. crnoBelo = CrnoBelo(tuple(polinja), tuple(goal), n)
  1164.  
  1165. answer = breadth_first_graph_search(crnoBelo)
  1166.  
  1167. print(answer.solution())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement