Advertisement
Guest User

Contravert

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