Как сгенерировать 2d-график сетки в Python?

#python #python-3.x #optimization #graph

#python #python-3.x #оптимизация #График

Вопрос:

Я пытаюсь представить такой график на Python:

График

Основные алгоритмы следующие, но я должен отдельно рассмотреть случаи, когда индексы вершины находятся вне диапазона графика.

 G = {(i, j): [(i-1, j), (i, j 1), (i 1, j), (i, j-1)] for i in range(0, n) for j in range(0, n)}
 

Затем я могу добавить 4 цикла 4 случая для углов графика или выполнить итерацию по приведенному выше графику и отфильтровать плохие случаи. Какое самое элегантное решение?

PS Я не могу использовать нестандартные библиотеки. Ответ, в котором график представлен списком списков, где индекс каждой строки — это номер вершины, а его значение — узлы, к которым он подключен, был бы еще лучше.

Комментарии:

1. @EnesErdogan Я сказал, что не могу использовать нестандартные библиотеки. Какой еще код вам нужен? Вот и все

Ответ №1:

Я думаю, что использование операторов потока управления для проверки условий при заполнении списка соседей или фильтрации соседей — это оба прекрасных подхода — моя естественная склонность создавать всех возможных соседей и фильтровать их, это может быть не лучшая идея для действительно огромных графиков.

Это можно сделать как функцию, но на всякий случай, если вам нужны дополнительные типы графиков или вам нужны дополнительные функциональные возможности (например, какой-нибудь метод, который возвращает, соединены ли две точки), вы также можете запустить класс, вот только один пример того, как вы могли бы это сделать:

 import typing
import itertools

class Graph(object):
    def __init__(self,
                 shape: typing.Tuple[int, int],
                 connectivity: str = "grid"):

        self.nodes = {} # type: typing.Dict[tuple, list]

        self.shape = shape
        self.connectivity = connectivity

        self._init_nodes()

    def _init_nodes(self):
        # iterate through all combinations of coordinates
        for x, y in itertools.product(range(self.shape[0]), range(self.shape[1])):

            # switch in case there are other connectivity types, but for this example just grid
            if self.connectivity == "grid":
                # make and all possible neighbors
                neighbors = [(x-1, y), (x 1, y), (x, y-1), (x, y 1)]
                # filter impossible neighbors
                neighbors = [n for n in neighbors if 0 <= n[0] <= self.shape[0]-1 and 0 <= n[1] <= self.shape[1]-1]
                self.nodes[(x,y)] = neighbors
                    
            else:
                raise NotImplementedError('only grid for now!!!')

 

Который дает словарь подключенных узлов, как у вас в вашем OP, хотя я не совсем уверен, отвечает ли это на вопрос, b / c не может сказать, о чем вы просите в последнем абзаце (мой плохой), поэтому дайте мне знать, если нет:

 >>> a_graph = Graph((5,5))
>>> pprint(a_graph.nodes)

{(0, 0): [(1, 0), (0, 1)],
 (0, 1): [(1, 1), (0, 0), (0, 2)],
 (0, 2): [(1, 2), (0, 1), (0, 3)],
 (0, 3): [(1, 3), (0, 2), (0, 4)],
 (0, 4): [(1, 4), (0, 3)],
 (1, 0): [(0, 0), (2, 0), (1, 1)],
 (1, 1): [(0, 1), (2, 1), (1, 0), (1, 2)],
 (1, 2): [(0, 2), (2, 2), (1, 1), (1, 3)],
 (1, 3): [(0, 3), (2, 3), (1, 2), (1, 4)],
 (1, 4): [(0, 4), (2, 4), (1, 3)],
 (2, 0): [(1, 0), (3, 0), (2, 1)],
 (2, 1): [(1, 1), (3, 1), (2, 0), (2, 2)],
 (2, 2): [(1, 2), (3, 2), (2, 1), (2, 3)],
 (2, 3): [(1, 3), (3, 3), (2, 2), (2, 4)],
 (2, 4): [(1, 4), (3, 4), (2, 3)],
 (3, 0): [(2, 0), (4, 0), (3, 1)],
 (3, 1): [(2, 1), (4, 1), (3, 0), (3, 2)],
 (3, 2): [(2, 2), (4, 2), (3, 1), (3, 3)],
 (3, 3): [(2, 3), (4, 3), (3, 2), (3, 4)],
 (3, 4): [(2, 4), (4, 4), (3, 3)],
 (4, 0): [(3, 0), (4, 1)],
 (4, 1): [(3, 1), (4, 0), (4, 2)],
 (4, 2): [(3, 2), (4, 1), (4, 3)],
 (4, 3): [(3, 3), (4, 2), (4, 4)],
 (4, 4): [(3, 4), (4, 3)]}
 

Комментарии:

1. Спасибо за ответ. Я думаю, добавление ifs / дополнительных циклов — единственный способ

2. Может быть какой-то способ сделать это в одной строке, но в Python это довольно не рекомендуется, и тогда вы не получите всех забавных и полезных бонусов от написания класса <3. Интересная задача программирования, хотя 🙂