Опубликован: 27.12.2010 | Доступ: свободный | Студентов: 1030 / 278 | Оценка: 5.00 / 5.00 | Длительность: 18:38:00
ISBN: 978-5-9556-0117-5
Специальности: Математик
Лекция 7:

Графы в компьютерной геометрии

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
Аннотация: Объекты, допускающие интерпретацию на языке теории графов, встречаются в математике и ее приложениях повсеместно. Компьютерная геометрия - не исключение. При этом в ней графы выступают и как техническое средство (сетка линий на поверхности, триангуляция параметризующей области и т. п.), и как объект изучения (прежде всего, оптимизационные задачи на гафах). Мы дадим здесь лишь самые простые определения, отсылая заинтересованных читателей к [13].

Графы и связанные с ними задачи

Определение 7.1.1. Графом называется пара G = (V,E) , где V - некоторое конечное множество, элементы которого называются вершинами, а E - семейство неупорядоченных пар (двухэлементных подмножеств) множества V, называемых ребрами. Если пара вершин v и w составляет ребро e = vw, то говорят, что эти вершины смежные или соседние. Также в этом случае говорят, что ребро e и вершина v инцидентны. Наконец, ребра, пересекающиеся по вершине, также называют смежными или соседними.

Замечание 7.1.1. Графы, которые мы только что определили, часто называют простыми. Аналогично определяются ориентированные графы (ребра - упорядоченные пары вершин) и мультиграфы (допускаются петли и кратные, т. е. соединяющие одни и те же вершины, ребра).

Граф G = (V,E) называется взвешенным, если на множестве его ребер задана весовая функция \omega : E \to R, которая обычно предполагается неотрицательной.

Красивое изображение графов в пакете Mathematica

Для продуктивной работы с графами часто требуется визуализировать граф наиболее наглядным образом. Особенно эта проблема важна в случае больших графов. В пакете Mathematica имеется ряд встроенных функций рисования графов на плоскости или в трехмерном пространстве, при котором расположение вершин и форма ребер вычисляется так, чтобы оптимизировать тот или иной "эстетический" функционал.

Перечислим основные функции, используемые в пакете Mathematica для изображения графов, и приведем примеры их использования. Стандартная функция GraphPlot[\{v_{i1} \to v_{j1}, v_{i2} \to v_{j2}, \dota \}] строит изображение мультиграфа, при котором вершина v_{ik} соединяется ребром с вершиной v_{jk}:

In[1]:= GraphPlot [{1 -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
                3 -> 1, 3 -> 2, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}]

При наведении курсора мыши на вершины графа возникают номера этих вершин. Заметьте, что пары {1, 2} встречаются три раза, - это изображено ребром кратности три. Кроме того, имеются петли, заданные двумя парами (4,4) и одной парой (3,3).

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

In[2] := GraphPlot [{1 -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
                 3 -> 1, 3 -> 2, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}, 
               DirectedEdges -> True]

Вот еще два формата команды GraphPlot:

GraphPlot[\{\{ v_{i1} \to v_{jl}, lbl_1}, \dots \}] приписывает ребру v_{ik} \to v_{jk} метку lbl_k:

In[3]:= GraphPlot[{1 -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
             {3 -> 1, "метка"}, 3 -> 2, 4 -> 1, 4 -> 2, 
               4 -> 4, 4 -> 4}]

GraphPlot[m] строит граф по матрице вершинной смежности, в которой на (i,j)-м месте стоит кратность ребра, идущего из вершины с номером i в вершину с номером j (если ребра нет, то кратность равна нулю). Заметим, что теперь для визуализации петель и кратных ребер нужно специально включать соответствующие опции SelfLoopStyle и MultiedgeStyle, которые по умолчанию выключены.

In[4]:= GraphPlot [{{0, 2, 0, 0}, {1, 0, 0, 0}, {1, 1, 1, 0}, 
               {1, 1, 0, 2}}, DirectedEdges -> True, 
            SelfLoopStyle -> True, MultiedgeStyle -> True]

In[5]:= GraphPlot [{{0, 2, 0, 0}, {1, 0, 0, 0}, 
            {1, 1, 1, 0}, {1, 1, 0, 2}}]

У команды GraphPlot[m] имеется много опций, с которыми можно ознакомиться, нажав кнопку MORE INFORMATION из Help для GraphPlot.

Команда GraphPlot3D имеет такой же формат, как и GraphPlot, однако изображает графы в трехмерном пространстве.

In[6] :=GraphPlot3D[{l -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
            3 -> 1, 3 -> 2, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}]

In[7]:=GraphPlot3D[{l -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
        3 -> 1, 3 -> 2, 3 -> 4, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}]

А вот пример более симпатичного изображения графа. Здесь опция EdgeRenderingFunction определяет функцию прорисовки ребра (в примере рисуется трубка Tube, ось которой задается последовательными точками ребра, возвращаемыми GraphPlot3D в первый аргумент #1 этой функции, 0.015 - радиус трубки), опция VertexRenderingFunction - функцию прорисовки вершин (они изображаются сферами):

In[8]:=GraphPlot3D[{l -> 2, 1 -> 2, 2 -> 1, 3 -> 3, 
             3 -> 1, 3 -> 2, 3 -> 4, 4 -> 1, 4 -> 2, 
             4 -> 4, 4 -> 4}, SelfLoopStyle -> True, 
          MultiedgeStyle -> True,
          EdgeRenderingFunction -> (Tube[#2, 0.015] &) , 
          VertexRenderingFunction -> ({ColorData["Atoms"]
                [RandomInteger[{l, 117}]], Sphere[#2, .08]} &) , 
          PlotStyle -> Directive[Specularity[White, 20] ] , 
          Boxed -> False]

Функция LayeredGraphPlot относится к так называемому иерархическому рисованию и изображает ориентированный граф, располагая вершины на уровнях так, чтобы доминантные вершины (те, в которые входит как можно меньше стрелочек) оказались наверху, а стрелочки были направлены преимущественно вниз. Ниже приведена программа, демонстрирующая, как меняется вид графа при изменении направления ровно одного ребра.

In[9] :=
      DynamicModule[{v, w, edge}, 
        v ={1 -> 2, 3 -> 1, 3 -> 2, 3 -> 4, 4 -> 1, 4 -> 2, 4 -> 4}; vv= v; 
        Manipulate[  
           If [ls ≠ "None", edge = List @@ ToExpression[ls] ; 
             vv = v / . Rule @@ edge -> Rule @@ (RotateLef t [edge]) ] ;  
           Row[{LayeredGraphPlot[v, VertexLabeling -> True,  
               EdgeRenderingFunction ->  
                    (If[(ls ≠ "None") && (# == edge) , {Red, Arrowheads[{{Automatic, 0.5}}] ,  
                         Arrow[#2]}, {Blue, Arrowheads[{{Automatic, 0.5}}], Arrow[#1]}] &) , 
                 ImageSize -> 250] ,  
               LayeredGraphPlot[vv, VertexLabeling -> True, ImageSize -> 250,  
                 EdgeRenderingFunction ->  
                    (If [(ls ≠ "None") && (#2 == RotateLeft[edge]) , 
                         {Red, Arrowheads [{ {Automatic , 0.5}}], Arrow[#l]}, 
                         {Blue, Arrowheads[{{Automatic, 0.5}}], Arrow[#1]}] &)]},"  " ] , 
        {{ls, "None", "ребро"}, { "None" } ≈ Join ≈ (ToString/@ v) } ] , 
      UnsavedVariables -> {vv, edge}]

Отметим, что у функции LayeredGraphPlot имеется еще один формат, а именно, LayeredGraphPlot[g,pos] , позволяющий задавать, с какой стороны располагать доминантные вершины. Возможные значения для pos -это Right, Left, Top и Bottom:

In[10] := Manipulate [
               LayeredGraphPlot[ 
                  {1 -> 2, 1 -> 2, 3 -> 1, 3 -> 2, 3 -> 4, 4 -> 1,
                    4 -> 2, 4 -> 4}, 
                  pos, 
                  VertexLabeling -> True] ,
               {
                 {pos, "Top", "Положение доминантной вершины"},
                 {Top, Bottom, Left, Right}
               }
            ]

Еще одна иерархическая функция изображения графов - это TreePlot. Несмотря на название, она применима не только к деревьям, но и к графам общего вида (в качестве деревьев у графов берутся остовные деревья их связных компонент, определения см. ниже). Ребра, не являющиеся петлями и кратными ребрами, изображаются отрезками, что может приводить к совмещению некоторых ребер (см. пример ниже). По своим форматам эта функция похожа на LayeredGraphPlot, однако она имеет дополнительный формат TreePlot[g,pos,v_k] , в котором v_k обозначает вершину, которую нужно выбрать в качестве корня. Кроме того, pos может принимать еще и значение Center:

In[11] :=Manipulate[TreePlot[{l -< 2, 1 -< 2, 3 -< 1, 
              3 -> 2, 3 -> 4, 4 -> 1, 4 -> 2, 4 -> 4}, 
           pos, root, VertexLabeling -> True,
           DirectedEdges -> True], 
       {{pos, Top, "Положение доминантной вершины"},
         {Top, Bottom, Left, Right, Center}}, 
       {{root, 1, "Доминантная вершина"}, {1, 2, 3, 4}}, 
       ControlPlacement -> Top]

У всех перечисленных выше функций рисования графов имеется полезная для решения геометрических задач опция VertexCoordinateRules, позволяющая явно указывать координаты вершин графа. Координаты можно задавать или в виде списка, или явно указывать, какой вершине какие координаты приписать, т. е. i \to \{х_i, y_i, \dots\}. Также вместо некоторых координат может стоять Automatic:

In[12] :=
   Manipulate[ 
      graphPlot[{l -> 2, 1 -> 2, 2 -> 1, 3 -> 3, 3 -> 1, 
            3 -> 2, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}, 
          VertexCoordinateRules -> p, PlotRange -> { {-1, 2}, {-1, 2}}, 
        AspectRatio -> Automatic, DirectedEdges -> True] , 
     {{P, {{0, 0}, {1, 0}, {0, 1}, {1, 1}}}, Locator}, 
     {graphPlot, {GraphPlot, LayeredGraphPlot, TreePlot}}]

In[13] : =
    DynamicModule[ {p0 , pp, plnit}, 
         p0 = {{0, 0}, {1, 0}, {0, 1}, {1, 1}}; 
         pInit = p0|[Drop [Range [4] , {1}]]];
         Manipulate [plnit = pO[[Drop [Range [4] , {automatic} ] ]] ; 
             pp = Maplndexed[First[#2] -> #1 &,
                Insert[p, {Automatic, Automatic}, automatic]]; 
            Quiet@graphPlot[{l -> 2, 1 -> 2, 2 -> 1, 3 -> 3,
                   3 -> 1, 3 -> 2, 4 -> 1, 4 -> 2, 4 -> 4, 4 -> 4}, 
                VertexCoordinateRules -> pp, PlotRange -> {{-1, 2}, {-1, 2}}, 
                AspectRatio -> Automatic, DirectedEdges -> True] , 
           {{p, plnit}, Locator},
           {graphPlot, {GraphPlot, LayeredGraphPlot, TreePlot}}, 
           {{automatic, 1, "Вершина, позиционируемая автоматически"}, 
             {1, 2, 3, 4}}], UnsavedVariables -> {pp, plnit} 
]

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >