Advertisement
fensa08

Untitled

Sep 6th, 2020
2,184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 23.55 KB | None | 0 0
  1. import sys
  2.  
  3.  
  4.  
  5. """
  6. Неинформирано пребарување во рамки на дрво.
  7. Во рамки на дрвото не разрешуваме јамки.
  8. """
  9.  
  10.  
  11. def tree_search(problem, fringe):
  12.     """ Пребарувај низ следбениците на даден проблем за да најдеш цел.
  13.  
  14.    :param problem: даден проблем
  15.    :type problem: Problem
  16.    :param fringe:  празна редица (queue)
  17.    :type fringe: FIFOQueue or Stack or PriorityQueue
  18.    :return: Node or None
  19.    :rtype: Node
  20.    """
  21.     fringe.append(Node(problem.initial))
  22.     while fringe:
  23.         node = fringe.pop()
  24.         print(node.state)
  25.         if problem.goal_test(node.state):
  26.             return node
  27.         fringe.extend(node.expand(problem))
  28.     return None
  29.  
  30.  
  31. def breadth_first_tree_search(problem):
  32.     """Експандирај го прво најплиткиот јазол во пребарувачкото дрво.
  33.  
  34.    :param problem: даден проблем
  35.    :type problem: Problem
  36.    :return: Node or None
  37.    :rtype: Node
  38.    """
  39.     return tree_search(problem, FIFOQueue())
  40.  
  41.  
  42. def depth_first_tree_search(problem):
  43.     """Експандирај го прво најдлабокиот јазол во пребарувачкото дрво.
  44.  
  45.    :param problem: даден проблем
  46.    :type problem: Problem
  47.    :return: Node or None
  48.    :rtype: Node
  49.    """
  50.     return tree_search(problem, Stack())
  51.  
  52.  
  53. """
  54. Неинформирано пребарување во рамки на граф
  55. Основната разлика е во тоа што овде не дозволуваме јамки,
  56. т.е. повторување на состојби
  57. """
  58.  
  59.  
  60. def graph_search(problem, fringe):
  61.     """Пребарувај низ следбениците на даден проблем за да најдеш цел.
  62.     Ако до дадена состојба стигнат два пата, употреби го најдобриот пат.
  63.  
  64.    :param problem: даден проблем
  65.    :type problem: Problem
  66.    :param fringe:  празна редица (queue)
  67.    :type fringe: FIFOQueue or Stack or PriorityQueue
  68.    :return: Node or None
  69.    :rtype: Node
  70.    """
  71.     closed = set()
  72.     fringe.append(Node(problem.initial))
  73.     while fringe:
  74.         node = fringe.pop()
  75.         if problem.goal_test(node.state):
  76.             return node
  77.         if node.state not in closed:
  78.             closed.add(node.state)
  79.             fringe.extend(node.expand(problem))
  80.     return None
  81.  
  82.  
  83. def breadth_first_graph_search(problem):
  84.     """Експандирај го прво најплиткиот јазол во пребарувачкиот граф.
  85.  
  86.    :param problem: даден проблем
  87.    :type problem: Problem
  88.    :return: Node or None
  89.    :rtype: Node
  90.    """
  91.     return graph_search(problem, FIFOQueue())
  92.  
  93.  
  94. def depth_first_graph_search(problem):
  95.     """Експандирај го прво најдлабокиот јазол во пребарувачкиот граф.
  96.  
  97.    :param problem: даден проблем
  98.    :type problem: Problem
  99.    :return: Node or None
  100.    :rtype: Node
  101.    """
  102.     return graph_search(problem, Stack())
  103.  
  104.  
  105. def depth_limited_search(problem, limit=50):
  106.     """Експандирај го прво најдлабокиот јазол во пребарувачкиот граф
  107.    со ограничена длабочина.
  108.  
  109.    :param problem: даден проблем
  110.    :type problem: Problem
  111.    :param limit: лимит за длабочината
  112.    :type limit: int
  113.    :return: Node or None
  114.    :rtype: Node
  115.    """
  116.  
  117.     def recursive_dls(node, problem, limit):
  118.         """Помошна функција за depth limited"""
  119.         cutoff_occurred = False
  120.         if problem.goal_test(node.state):
  121.             return node
  122.         elif node.depth == limit:
  123.             return 'cutoff'
  124.         else:
  125.             for successor in node.expand(problem):
  126.                 result = recursive_dls(successor, problem, limit)
  127.                 if result == 'cutoff':
  128.                     cutoff_occurred = True
  129.                 elif result is not None:
  130.                     return result
  131.         if cutoff_occurred:
  132.             return 'cutoff'
  133.         return None
  134.  
  135.     return recursive_dls(Node(problem.initial), problem, limit)
  136.  
  137.  
  138. def iterative_deepening_search(problem):
  139.     """Експандирај го прво најдлабокиот јазол во пребарувачкиот граф
  140.    со ограничена длабочина, со итеративно зголемување на длабочината.
  141.  
  142.    :param problem: даден проблем
  143.    :type problem: Problem
  144.    :return: Node or None
  145.    :rtype: Node
  146.    """
  147.     for depth in range(sys.maxsize):
  148.         result = depth_limited_search(problem, depth)
  149.         if result is not 'cutoff':
  150.             return result
  151.  
  152.  
  153. def uniform_cost_search(problem):
  154.     """Експандирај го прво јазолот со најниска цена во пребарувачкиот граф.
  155.  
  156.    :param problem: даден проблем
  157.    :type problem: Problem
  158.    :return: Node or None
  159.    :rtype: Node
  160.    """
  161.     return graph_search(problem, PriorityQueue(min, lambda a: a.path_cost))
  162.  
  163.  
  164. import bisect
  165.  
  166.  
  167. """
  168. Дефинирање на класа за структурата на проблемот кој ќе го решаваме со пребарување.
  169. Класата Problem е апстрактна класа од која правиме наследување за дефинирање на основните
  170. карактеристики на секој проблем што сакаме да го решиме
  171. """
  172.  
  173.  
  174. class Problem:
  175.     def __init__(self, initial, goal=None):
  176.         self.initial = initial
  177.         self.goal = goal
  178.  
  179.     def successor(self, state):
  180.         """За дадена состојба, врати речник од парови {акција : состојба}
  181.        достапни од оваа состојба. Ако има многу следбеници, употребете
  182.        итератор кој би ги генерирал следбениците еден по еден, наместо да
  183.        ги генерирате сите одеднаш.
  184.  
  185.        :param state: дадена состојба
  186.        :return:  речник од парови {акција : состојба} достапни од оваа
  187.                  состојба
  188.        :rtype: dict
  189.        """
  190.         raise NotImplementedError
  191.  
  192.     def actions(self, state):
  193.         """За дадена состојба state, врати листа од сите акции што може да
  194.        се применат над таа состојба
  195.  
  196.        :param state: дадена состојба
  197.        :return: листа на акции
  198.        :rtype: list
  199.        """
  200.         raise NotImplementedError
  201.  
  202.     def result(self, state, action):
  203.         """За дадена состојба state и акција action, врати ја состојбата
  204.        што се добива со примена на акцијата над состојбата
  205.  
  206.        :param state: дадена состојба
  207.        :param action: дадена акција
  208.        :return: резултантна состојба
  209.        """
  210.         raise NotImplementedError
  211.  
  212.     def goal_test(self, state):
  213.         """Врати True ако state е целна состојба. Даденава имплементација
  214.        на методот директно ја споредува state со self.goal, како што е
  215.        специфицирана во конструкторот. Имплементирајте го овој метод ако
  216.        проверката со една целна состојба self.goal не е доволна.
  217.  
  218.        :param state: дадена состојба
  219.        :return: дали дадената состојба е целна состојба
  220.        :rtype: bool
  221.        """
  222.         return state == self.goal
  223.  
  224.     def path_cost(self, c, state1, action, state2):
  225.         """Врати ја цената на решавачкиот пат кој пристигнува во состојбата
  226.        state2 од состојбата state1 преку акцијата action, претпоставувајќи
  227.        дека цената на патот до состојбата state1 е c. Ако проблемот е таков
  228.        што патот не е важен, оваа функција ќе ја разгледува само состојбата
  229.        state2. Ако патот е важен, ќе ја разгледува цената c и можеби и
  230.        state1 и action. Даденава имплементација му доделува цена 1 на секој
  231.        чекор од патот.
  232.  
  233.        :param c: цена на патот до состојбата state1
  234.        :param state1: дадена моментална состојба
  235.        :param action: акција која треба да се изврши
  236.        :param state2: состојба во која треба да се стигне
  237.        :return: цена на патот по извршување на акцијата
  238.        :rtype: float
  239.        """
  240.         return c + 1
  241.  
  242.     def value(self):
  243.         """За проблеми на оптимизација, секоја состојба си има вредност.
  244.        Hill-climbing и сличните алгоритми се обидуваат да ја максимизираат
  245.        оваа вредност.
  246.  
  247.        :return: вредност на состојба
  248.        :rtype: float
  249.        """
  250.         raise NotImplementedError
  251.  
  252.  
  253. """
  254. Дефинирање на класата за структурата на јазел од пребарување.
  255. Класата Node не се наследува
  256. """
  257.  
  258.  
  259. class Node:
  260.     def __init__(self, state, parent=None, action=None, path_cost=0):
  261.         """Креирај јазол од пребарувачкото дрво, добиен од parent со примена
  262.        на акцијата action
  263.  
  264.        :param state: моментална состојба (current state)
  265.        :param parent: родителска состојба (parent state)
  266.        :param action: акција (action)
  267.        :param path_cost: цена на патот (path cost)
  268.        """
  269.         self.state = state
  270.         self.parent = parent
  271.         self.action = action
  272.         self.path_cost = path_cost
  273.         self.depth = 0  # search depth
  274.         if parent:
  275.             self.depth = parent.depth + 1
  276.  
  277.     def __repr__(self):
  278.         return "<Node %s>" % (self.state,)
  279.  
  280.     def __lt__(self, node):
  281.         return self.state < node.state
  282.  
  283.     def expand(self, problem):
  284.         """Излистај ги јазлите достапни во еден чекор од овој јазол.
  285.  
  286.        :param problem: даден проблем
  287.        :return: листа на достапни јазли во еден чекор
  288.        :rtype: list(Node)
  289.        """
  290.  
  291.         return [self.child_node(problem, action)
  292.                 for action in problem.actions(self.state)]
  293.  
  294.     def child_node(self, problem, action):
  295.         """Дете јазел
  296.  
  297.        :param problem: даден проблем
  298.        :param action: дадена акција
  299.        :return: достапен јазел според дадената акција
  300.        :rtype: Node
  301.        """
  302.         next_state = problem.result(self.state, action)
  303.         return Node(next_state, self, action,
  304.                     problem.path_cost(self.path_cost, self.state,
  305.                                       action, next_state))
  306.  
  307.     def solution(self):
  308.         """Врати ја секвенцата од акции за да се стигне од коренот до овој јазол.
  309.  
  310.        :return: секвенцата од акции
  311.        :rtype: list
  312.        """
  313.         return [node.action for node in self.path()[1:]]
  314.  
  315.     def solve(self):
  316.         """Врати ја секвенцата од состојби за да се стигне од коренот до овој јазол.
  317.  
  318.        :return: листа од состојби
  319.        :rtype: list
  320.        """
  321.         return [node.state for node in self.path()[0:]]
  322.  
  323.     def path(self):
  324.         """Врати ја листата од јазли што го формираат патот од коренот до овој јазол.
  325.  
  326.        :return: листа од јазли од патот
  327.        :rtype: list(Node)
  328.        """
  329.         x, result = self, []
  330.         while x:
  331.             result.append(x)
  332.             x = x.parent
  333.         result.reverse()
  334.         return result
  335.  
  336.     """Сакаме редицата од јазли кај breadth_first_search или
  337.    astar_search да не содржи состојби - дупликати, па јазлите што
  338.    содржат иста состојба ги третираме како исти. [Проблем: ова може
  339.    да не биде пожелно во други ситуации.]"""
  340.  
  341.     def __eq__(self, other):
  342.         return isinstance(other, Node) and self.state == other.state
  343.  
  344.     def __hash__(self):
  345.         return hash(self.state)
  346.  
  347.  
  348. """
  349. Дефинирање на помошни структури за чување на листата на генерирани, но непроверени јазли
  350. """
  351.  
  352.  
  353. class Queue:
  354.     """Queue е апстрактна класа / интерфејс. Постојат 3 типа:
  355.        Stack(): Last In First Out Queue (стек).
  356.        FIFOQueue(): First In First Out Queue (редица).
  357.        PriorityQueue(order, f): Queue во сортиран редослед (подразбирливо,од најмалиот кон
  358.                                 најголемиот јазол).
  359.    """
  360.  
  361.     def __init__(self):
  362.         raise NotImplementedError
  363.  
  364.     def append(self, item):
  365.         """Додади го елементот item во редицата
  366.  
  367.        :param item: даден елемент
  368.        :return: None
  369.        """
  370.         raise NotImplementedError
  371.  
  372.     def extend(self, items):
  373.         """Додади ги елементите items во редицата
  374.  
  375.        :param items: дадени елементи
  376.        :return: None
  377.        """
  378.         raise NotImplementedError
  379.  
  380.     def pop(self):
  381.         """Врати го првиот елемент од редицата
  382.  
  383.        :return: прв елемент
  384.        """
  385.         raise NotImplementedError
  386.  
  387.     def __len__(self):
  388.         """Врати го бројот на елементи во редицата
  389.  
  390.        :return: број на елементи во редицата
  391.        :rtype: int
  392.        """
  393.         raise NotImplementedError
  394.  
  395.     def __contains__(self, item):
  396.         """Проверка дали редицата го содржи елементот item
  397.  
  398.        :param item: даден елемент
  399.        :return: дали queue го содржи item
  400.        :rtype: bool
  401.        """
  402.         raise NotImplementedError
  403.  
  404.  
  405. class Stack(Queue):
  406.     """Last-In-First-Out Queue."""
  407.  
  408.     def __init__(self):
  409.         self.data = []
  410.  
  411.     def append(self, item):
  412.         self.data.append(item)
  413.  
  414.     def extend(self, items):
  415.         self.data.extend(items)
  416.  
  417.     def pop(self):
  418.         return self.data.pop()
  419.  
  420.     def __len__(self):
  421.         return len(self.data)
  422.  
  423.     def __contains__(self, item):
  424.         return item in self.data
  425.  
  426.  
  427. class FIFOQueue(Queue):
  428.     """First-In-First-Out Queue."""
  429.  
  430.     def __init__(self):
  431.         self.data = []
  432.  
  433.     def append(self, item):
  434.         self.data.append(item)
  435.  
  436.     def extend(self, items):
  437.         self.data.extend(items)
  438.  
  439.     def pop(self):
  440.         return self.data.pop(0)
  441.  
  442.     def __len__(self):
  443.         return len(self.data)
  444.  
  445.     def __contains__(self, item):
  446.         return item in self.data
  447.  
  448.  
  449. class PriorityQueue(Queue):
  450.     """Редица во која прво се враќа минималниот (или максималниот) елемент
  451.    (како што е определено со f и order). Оваа структура се користи кај
  452.    информирано пребарување"""
  453.     """"""
  454.  
  455.     def __init__(self, order=min, f=lambda x: x):
  456.         """
  457.        :param order: функција за подредување, ако order е min, се враќа елементот
  458.                      со минимална f(x); ако order е max, тогаш се враќа елементот
  459.                      со максимална f(x).
  460.        :param f: функција f(x)
  461.        """
  462.         assert order in [min, max]
  463.         self.data = []
  464.         self.order = order
  465.         self.f = f
  466.  
  467.     def append(self, item):
  468.         bisect.insort_right(self.data, (self.f(item), item))
  469.  
  470.     def extend(self, items):
  471.         for item in items:
  472.             bisect.insort_right(self.data, (self.f(item), item))
  473.  
  474.     def pop(self):
  475.         if self.order == min:
  476.             return self.data.pop(0)[1]
  477.         return self.data.pop()[1]
  478.  
  479.     def __len__(self):
  480.         return len(self.data)
  481.  
  482.     def __contains__(self, item):
  483.         return any(item == pair[1] for pair in self.data)
  484.  
  485.     def __getitem__(self, key):
  486.         for _, item in self.data:
  487.             if item == key:
  488.                 return item
  489.  
  490.     def __delitem__(self, key):
  491.         for i, (value, item) in enumerate(self.data):
  492.             if item == key:
  493.                 self.data.pop(i)
  494.  
  495.  
  496.  
  497.  
  498. def izedi_tocka(x,y,tocki):
  499.     tocki_new = [tocka for tocka in tocki if tocka != (x,y)]
  500.     tocki_new = tuple(tocki_new)
  501.     return  tocki_new
  502.  
  503.  
  504.  
  505. def nazad(x,y,nasoka,tocki):
  506.  
  507.     x_new = x
  508.     y_new = y
  509.     nasoka_new = nasoka
  510.  
  511.     if nasoka == "istok":
  512.         x_new = x_new - 1
  513.         nasoka_new = "zapad"
  514.     elif nasoka == "jug":
  515.         y_new = y_new + 1
  516.         nasoka_new = "sever"
  517.     elif nasoka == "sever":
  518.         y_new = y_new - 1
  519.         nasoka_new = "jug"
  520.     else:
  521.         nasoka_new = "istok"        # todo proveri ovde dali se dobri
  522.         x_new = x_new + 1
  523.  
  524.     tocki_new = izedi_tocka(x_new, y_new, tocki)
  525.  
  526.     return (x_new, y_new, nasoka_new, tocki_new)
  527.  
  528.  
  529. def pravo(x,y,nasoka,tocki):
  530.  
  531.     x_new = x
  532.     y_new = y
  533.     if nasoka == "istok":
  534.         x_new = x_new + 1
  535.     elif nasoka == "sever":
  536.         y_new = y_new + 1
  537.     elif nasoka ==  "zapad":
  538.         x_new = x_new - 1
  539.     else:
  540.         y_new = y_new - 1
  541.  
  542.     tocki_new = izedi_tocka(x_new,y_new, tocki)
  543.  
  544.     return (x_new,y_new, nasoka,tocki_new)
  545.  
  546.  
  547.  
  548. def change_direction(nasoka, left):             # proveri ovde
  549.  
  550.     kompas = ["istok", "sever", "zapad", "jug"]
  551.     indeks = kompas.index(nasoka)
  552.     if left:                                    # Levo:  pozicija + 1
  553.         if indeks == 3:
  554.             return kompas[0]
  555.         return kompas[1 + indeks]
  556.     else:                                       # Desno : pozicija - 1
  557.         return kompas[indeks-1]
  558.  
  559.  
  560. def levo(x,y,nasoka,tocki):
  561.     nasoka_new = change_direction(nasoka, True)
  562.  
  563.     x_new = x
  564.     y_new = y
  565.     if nasoka_new == "istok":
  566.         x_new = x_new + 1
  567.     elif nasoka_new == "sever":
  568.         y_new = y_new + 1
  569.     elif nasoka_new == "zapad":
  570.         x_new = x_new - 1
  571.     else:
  572.         y_new = y_new - 1
  573.  
  574.     tocki_new = izedi_tocka(x_new, y_new, tocki)
  575.  
  576.     return (x_new, y_new, nasoka_new, tocki_new)
  577.  
  578.  
  579. def desno(x,y,nasoka,tocki):
  580.     nasoka_new = change_direction(nasoka,False)
  581.  
  582.     x_new = x
  583.     y_new = y
  584.     if nasoka_new == "istok":
  585.         x_new = x_new + 1
  586.     elif nasoka_new == "sever":
  587.         y_new = y_new + 1
  588.     elif nasoka_new == "zapad":
  589.         x_new = x_new - 1
  590.     else:
  591.         y_new = y_new - 1
  592.  
  593.     tocki_new = izedi_tocka(x_new, y_new, tocki)
  594.  
  595.     return (x_new, y_new, nasoka_new, tocki_new)
  596.  
  597.  
  598. """
  599.   return pravo(x,y,nasoka_new,tocki)
  600. """
  601.  
  602.  
  603.  
  604.  
  605.  
  606. class Pacman(Problem):
  607.  
  608.     obstacles = [           #todo smeni gi oviee!!!!!!!!!!!
  609.  
  610.         [1, 10],
  611.         [2, 10],
  612.         [3, 10],
  613.         [4, 10],
  614.         [7, 10],
  615.         [1, 9],
  616.         [9, 9],
  617.         [10, 9],
  618.         [5, 8],
  619.         [9, 8],
  620.         [10, 8],
  621.         [1, 7],
  622.         [4, 7],
  623.         [5, 7],
  624.         [6, 7],
  625.         [5, 6],
  626.         [2, 5],
  627.         [9, 5],
  628.         [10, 5],
  629.         [2, 4],
  630.         [2, 3],
  631.         [7, 3],
  632.         [5, 2],
  633.         [6, 2],
  634.         [7, 2],
  635.         [9, 2],
  636.         [7, 1]
  637.     ]
  638.  
  639.     def __init__(self,initial, goal = None):
  640.         super().__init__(initial,goal)
  641.  
  642.  
  643.     def successor(self, state):
  644.  
  645.         successors = dict()
  646.  
  647.         x = state[0]
  648.         y = state[1]
  649.         nasoka = state[2]
  650.         tocki = state[3]
  651.  
  652.  
  653.         #prodolzi pravo
  654.         x_new,y_new,nasoka_new,tocki_new = pravo(x,y,nasoka,tocki)
  655.         state_new = x_new,y_new,nasoka_new,tocki_new
  656.         if [x_new,y_new] not in self.obstacles and state_new != state and 0 < x_new < 11 and 0 < y_new < 11:
  657.             successors["ProdolzhiPravo"] = (x_new, y_new, nasoka_new, tocki_new)
  658.  
  659.         #todo ProdolzhiNazad
  660.         x_new, y_new, nasoka_new, tocki_new = nazad(x, y, nasoka, tocki)
  661.         state_new = x_new, y_new, nasoka_new, tocki_new
  662.         if [x_new,y_new] not in self.obstacles and state_new != state and 0 < x_new < 11 and 0 < y_new < 11:
  663.             successors["ProdolzhiNazad"] = (x_new, y_new, nasoka_new, tocki_new)
  664.  
  665.         #todo SvrtiLevo
  666.         x_new, y_new, nasoka_new, tocki_new = levo(x, y, nasoka, tocki)
  667.         state_new = x_new, y_new, nasoka_new, tocki_new
  668.         if [x_new, y_new] not in self.obstacles and state_new != state and 0 < x_new < 11 and 0 < y_new < 11:
  669.             successors["SvrtiLevo"] = (x_new, y_new, nasoka_new, tocki_new)
  670.  
  671.         # todo SvrtiDesno
  672.         x_new, y_new, nasoka_new, tocki_new = desno(x, y, nasoka, tocki)
  673.         state_new = x_new, y_new, nasoka_new, tocki_new
  674.         if [x_new, y_new] not in self.obstacles and state_new != state and 0 < x_new < 11 and 0 < y_new < 11:
  675.             successors["SvrtiDesno"] = (x_new, y_new, nasoka_new, tocki_new)
  676.  
  677.         return successors
  678.  
  679.     def result(self, state, action):
  680.         """За дадена состојба state и акција action, врати ја состојбата
  681.        што се добива со примена на акцијата над состојбата
  682.  
  683.        :param state: дадена состојба
  684.        :param action: дадена акција
  685.        :return: резултантна состојба
  686.        """
  687.         return self.successor(state)[action]
  688.  
  689.     def actions(self, state):
  690.         return self.successor(state).keys()
  691.  
  692.  
  693.     def goal_test(self, state):
  694.         if state[3] != None and len(state[3]) != 0:
  695.             return False
  696.         return True
  697.  
  698.  
  699.  
  700.  
  701.  
  702. if __name__ == "__main__":
  703.  
  704.  
  705.     x = int(input()) + 1
  706.     y = int(input()) + 1
  707.     nasoka = input()
  708.     tocki = []
  709.     brtocki = int(input())
  710.     for k in range(0,brtocki):
  711.         i,j = input().split(",")
  712.         i = int(i) + 1
  713.         j = int(j) + 1
  714.         tocki.append((i,j))
  715.     tocki = tuple(tocki)
  716.  
  717.     pacman_problem = Pacman((x,y,nasoka,tocki))
  718.     print(breadth_first_graph_search(pacman_problem).solution())
  719.  
  720.     """
  721.    sto se menja?  
  722.        - tocki
  723.        - pozicija na covece
  724.        - nasoka
  725.    """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement