Birisi bana basit bir şekilde, yönlendirilmiş çevrimsiz grafiğin ne olduğunu açıklayabilir mi?


109

Birisi bana basit bir şekilde, yönlendirilmiş çevrimsiz grafiğin ne olduğunu açıklayabilir mi? Wikipedia'ya baktım ama programlamada kullanımını gerçekten görmemi sağlamıyor.


26
Wikipedia sıklıkla, yeni başlayanların kavraması için çok fazla çalışma gerektiren ezici teknik içerik içerir. Matematik yardım sitelerinin çoğu bu konuda üstündür, ancak maalesef hesaplama ile ilgili konulara girme eğilimindedirler.
Jonathon Faust

Yanıtlar:


86

diğer noktaları işaret eden çizgiler içeren noktalar


23
Bu en iyi cevaplardan biridir çünkü karmaşık terminolojiye gömülü basit bir kavramın ne olduğunu açıklamanın basit bir yoludur (eğer bu soruyu soruyorsak, grafik teorisini bilmeyebiliriz ... hatta bilmemiz gerekebilir). Benim varyantım, "aynı bara iki kez asla gidemeyeceğiniz yerde bar atlama" gibi bir şey olurdu. Başka bir cevabın soy ağacı örneği muhtemelen kavramsal olarak daha basit olsa da, özellikle üniversite öğrencisi veya alkolik olmayanlar için.
Tom Harrison

27
... in one direction
Mark Robson

3
Bu, doğası gereği karmaşık bir kavramı mümkün olandan daha az terimlerle ifade edememenin iyi bir örneğidir. Bu nedenle Öklid'in beşinci postülası hala mevcuttur.
Xaqron

4
"Çizgilerin döngü oluşturmadığı yerlerde" eklemeniz gerekir, aksi takdirde yalnızca yönlendirilmiş bir döngüsel grafiği değil, yönlendirilmiş bir grafiği tanımlarsınız.
Pharap

"Çizgileri olan noktalar başka noktaları işaret ediyor, döngüleri yok" bir gelişme olacaktır.
John DeRegnaucourt

172

grafik = birbirine kenarlarla bağlı düğümlerden oluşan yapı

yönlendirilmiş = düğümler (kenarlar) arasındaki bağlantıların bir yönü vardır: A -> B, B -> A ile aynı değildir

asyclic = "dairesel olmayan" = kenarları takip ederek düğümden düğüme geçtiğinizde, aynı düğümle ikinci kez asla karşılaşmayacaksınız.

Yönlendirilmiş döngüsel olmayan grafiğin güzel bir örneği ağaçtır. Bununla birlikte, tüm yönlendirilmiş döngüsel olmayan grafiklerin ağaç olmadığını unutmayın.


Düğümlerin ne olduğunu anlıyorum. "Kenar" dediğinizde, Düğüm A'dan Düğüm B'ye işaret eden bir oku mu kastediyorsunuz?
appshare.co

Daha iyi açıklama. Peki bunun programlama ile ne ilgisi var? Fonksiyonel programlama ile ilgili mi?
appshare.co

2
Tipik olarak bir okla temsil edilir, ancak gerçekte sadece A ve B arasında bir ilişki vardır. Programınızda bu, bu iki düğümü temsil eden endekslerde bir bitişik matrisinde gerçek bir değer olabilir.
tvanfosson

42
Yönlendirilmiş tüm ağaçlar DAG'lardır, ancak tüm DAG'ler ağaç değildir. DAG A-> B, A-> C, B-> C bir ağaç olarak temsil edilemez çünkü C düğümünün birden fazla ebeveyni vardır.
Jason S

2
DAG'leri ağaçlardan ayıran tek özellik kenarların yönü değildir. DAG, ağaçtan farklı olarak | V | -1'den fazla kenara sahip olabilir. Örneğin, A-> B, A-> C, B-> D, C-> D bir DAG'dir ancak aynı sayıda kenar ve düğüme sahip olduğu için açıkça bir ağaç değildir.
Anonim Mus

49

DAG'nin (Yönlendirilmiş Asiklik Grafik) anlamını belirten birçok yanıt görüyorum, ancak uygulamalarında yanıt yok. İşte çok basit bir tane -

Ön koşul grafiği - Bir mühendislik kursu sırasında her öğrenci, ön koşullar gibi gereksinimleri izleyen konuları seçme göreviyle karşı karşıyadır. Şimdi, Algoritmalar [A] üzerine bir ön koşul dersi olmadan Yapay Zeka [B] dersi alamayacağınız açıktır. Dolayısıyla B, A'ya bağlıdır veya daha iyi terimlerle A'nın B'ye yönelik bir kenarı vardır. Dolayısıyla, B Düğümüne ulaşmak için Düğüm A'yı ziyaret etmeniz gerekir. , Directed Acyclic Graph olacak.

Bir döngü olsaydı o zaman bir kursu asla tamamlamazdınız: p

Üniversitede öğrencilerin derslere kaydolmalarına izin veren bir yazılım sistemi, öğrencinin mevcut kursa kaydolmadan önce ön koşullu bir ders aldığından emin olmak için konuları düğümler olarak modelleyebilir.

Profesörüm bu benzetmeyi yaptı ve karmaşık bir kavram kullanmak yerine DAG'yi anlamama en iyi şekilde yardımcı oldu!

Başka bir gerçek zamanlı örnek -> DAG'lerin sürüm sisteminde nasıl kullanılabileceğine dair Gerçek Zamanlı örnek


4
Bu en yüksek dereceli cevap olmalıdır. Basit benzetme ve OP'nin kolayca anlayamadığı metin kitabı tanımını kullanmaz.
kimathie

25

Programlamada yönlendirilmiş çevrimsiz grafiğin örnek kullanımları, bağlantı ve nedenselliği temsil eden aşağı yukarı her şeyi içerir.

Örneğin, çalışma zamanında konfigüre edilebilen bir hesaplama hattınız olduğunu varsayalım. Buna bir örnek olarak, A, B, C, D, E, F ve G hesaplamalarının birbirine bağlı olduğunu varsayalım: A, C'ye, C, E ve F'ye, B, D ve E'ye ve D, F. Bu bir DAG olarak temsil edilebilir. DAG'yi hafızaya aldıktan sonra, algoritmaları aşağıdakilere yazabilirsiniz:

  • hesaplamaların doğru sırada ( topolojik sıralama ) değerlendirildiğinden emin olun
  • Hesaplamalar paralel olarak yapılabiliyorsa, ancak her hesaplamanın maksimum yürütme süresi varsa, tüm setin maksimum yürütme süresini hesaplayabilirsiniz.

diğer birçok şeyin yanı sıra.

Uygulama programlama alanının dışında, herhangi bir düzgün otomatikleştirilmiş yapı aracı (make, ant, scons, vb.), Bir programın bileşenlerinin doğru derleme sırasını sağlamak için DAG'leri kullanacaktır.


Nedensellikten bahsetmek için +1. Bu, bir sürecin çıktısının bir veya daha fazla diğer işlem için girdi olduğu karmaşık bir sistemi temsil etmeniz gerektiğinde ortaya çıkar.
Alex Feinman

14

Çeşitli cevaplar grafik kullanımıyla ilgili örnekler vermiştir (örneğin ağ modellemesi) ve siz "bunun programlama ile ne ilgisi var?" Diye sordunuz.

Bu alt sorunun cevabı, programlamayla pek bir ilgisinin olmamasıdır. Problem çözmeyle ilgisi var.

Bağlantılı listelerin belirli problem sınıfları için kullanılan veri yapıları olması gibi, grafikler de belirli ilişkileri temsil etmek için kullanışlıdır. Bağlı listeler, ağaçlar, grafikler ve diğer soyut yapılar, yalnızca bunları kodda uygulayabileceğiniz programlama ile bağlantılıdır. Daha yüksek bir soyutlama seviyesinde var olurlar. Bu programlama ile ilgili değil, sorunların çözümünde veri yapılarını uygulamakla ilgili.


Programlamada uygulanabilir. Evet, grafik gerçek dünyada bilgisayardan bağımsız olarak var olduğu için bunu seviyorum!
appshare.co

13

Yönlendirilmiş Asiklik Grafikler (DAG), onları diğer grafiklerden ayıran aşağıdaki özelliklere sahiptir:

  1. Kenarları yön gösterir.
  2. Döngüleri yok.

Şu anda tek bir kullanım düşünebilirim - DAG ( Wait-For-Graphs olarak bilinir - daha teknik ayrıntılar ), bir dizi süreç ve kaynak arasındaki bağımlılıkları gösterdikleri için kilitlenmeleri tespit etmede kullanışlıdır (her ikisi de DAG'deki düğümlerdir) . Bir döngü algılandığında kilitlenme meydana gelir.


1
Andriyev, kilitlenme örneği için +1. Bu aslında MySQL'in InnoDB motoru tarafından kullanılıyor ve buna "grafik için bekle" diyorlar, "bu satırın o satırdaki kilidin serbest bırakılmasını beklemesi gerekiyor"
Roland Bouman

evet, ismiyle çok haklısın - Grafiği Bekle. Bazıları bunu nasıl kaçırdı. Yanıt güncellendi. :)
Arnkrishn

Bir bağımlılık olduğunu nasıl anlarlar? İki düğümün ortak bir atası olup olmadığını kontrol ederek mi?
appshare.co

Bu bağlantı - cis.temple.edu/~ingargio/cis307/readings/deadlock.html daha fazla teknik detaya sahiptir.
Arnkrishn

11

Zaten temel grafik terminolojisini bildiğinizi varsayıyorum; aksi takdirde grafik teorisi hakkındaki makaleden başlamalısınız .

Yönlü , kenarların (bağlantıların) yönlere sahip olduğu gerçeğini ifade eder. Şemada bu yönler oklarla gösterilmiştir. Bunun tersi, kenarları yön belirtmeyen yönsüz bir grafiktir.

Döngüsel olmayan , herhangi bir rastgele X düğümünden başlarsanız ve olası tüm kenarlardan geçerseniz, önceden kullanılmış bir kenara geri dönmeden X'e geri dönemeyeceğiniz anlamına gelir.

Birkaç uygulama:

  • Tablolar; bu DAG makalesinde açıklanmıştır .
  • Revizyon kontrolü : Bu sayfadaki şemaya bakarsanız, revizyon kontrollü kodun evriminin yönlendirildiğini (bu şemada "aşağı" olduğunu) ve döngüsel olmadığını (asla "yukarı" geri dönmediğini) göreceksiniz. .
  • Aile ağacı: yönlendirilir (siz ebeveyninizin çocuğusunuz, tam tersi değil) ve döngüsel değildir (atalarınız asla sizin soyundan gelemez).

5

DAG, her şeyin aynı yönde aktığı ve hiçbir düğümün kendisine geri dönemediği bir grafiktir.

Soy ağaçlarını düşünün; onlar aslında DAG'lardır.

Tüm DAG'lerde

  • Düğümler (verilerin saklanacağı yerler)
  • Yönlendirilmiş Kenarlar (aynı yönü gösteren)
  • Atalara ait bir düğüm (ebeveynleri olmayan bir düğüm)
  • Yapraklar (çocuğu olmayan düğümler)

DAG'ler ağaçlardan farklıdır. Ağaç benzeri bir yapıda, her iki düğüm arasında benzersiz bir yol olmalıdır. DAG'lerde, bir düğümün iki ana düğümü olabilir.

İşte DAG'ler hakkında güzel bir makale . Umarım bu yardımcı olur.


4

Her türden grafik, çeşitli farklı gerçek dünya ilişkilerini modellemek için programlamada kullanılır. Örneğin, bir sosyal ağ genellikle bir grafikle temsil edilir (bu durumda döngüsel). Aynı şekilde ağ topolojileri, aile ağaçları, havayolu rotaları, ...


2

Bir kaynak kodu veya hatta üç adres (TAC) kodu perspektifinden, sorunu bu sayfada gerçekten kolayca görselleştirebilirsiniz ...

http://cgm.cs.mcgill.ca/~hagha/topic30/topic30.html#Exptree

İfade ağacı bölümüne gidip biraz aşağıya giderseniz, ağacın "topolojik sıralaması" ve ifadenin nasıl değerlendirileceğine ilişkin algoritma gösterilir.

Bu durumda, DAG'yi ifadeleri değerlendirmek için kullanabilirsiniz, çünkü değerlendirme normal olarak yorumlanır ve böyle bir DAG değerlendiricisi kullanmak, temelde basit yorumlayıcıları daha hızlı hale getirir çünkü bir yığına itip fırlatmaz ve aynı zamanda ortadan kaldırır. ortak alt ifadeler.

Antik Mısır dilinde olmayan (yani İngilizce) DAG'yi hesaplamak için temel algoritma şudur:

1) DAG nesnenizi böyle yapın

Canlı bir listeye ihtiyacınız vardır ve bu liste tüm mevcut canlı DAG düğümlerini ve DAG alt ifadelerini içerir. DAG alt ifadesi bir DAG Düğümüdür veya buna dahili düğüm de diyebilirsiniz. Canlı DAG Düğümü ile kastettiğim, bir X değişkenine atarsanız o zaman canlı hale gelir. Daha sonra X'i kullanan yaygın bir alt ifade bu örneği kullanır. X'e tekrar atanırsa, YENİ DAG DÜĞÜMÜ oluşturulur ve canlı listeye eklenir ve eski X kaldırılır, böylece X kullanan bir sonraki alt ifade yeni örneğe atıfta bulunacak ve bu nedenle alt ifadelerle çakışmayacaktır. sadece aynı değişken adını kullanın.

Bir X değişkenine atadığınızda, yeni atama eski değeri kullanan alt ifadelerin anlamını geçersiz kıldığından, tesadüfen atama noktasında canlı olan tüm DAG alt ifade düğümleri canlı kalmaz.

class Dag {
  TList LiveList;
  DagNode Root;
}

// In your DagNode you need a way to refer to the original things that
// the DAG is computed from. In this case I just assume an integer index
// into the list of variables and also an integer index for the opertor for
// Nodes that refer to operators. Obviously you can create sub-classes for
// different kinds of Dag Nodes.
class DagNode {
  int Variable;
  int Operator;// You can also use a class
  DagNode Left;
  DagNode Right;
  DagNodeList Parents;
}

Öyleyse yaptığınız şey, örneğin kaynak koddaki bir ifade ağacı gibi kendi kodunuzla ağacınızda dolaşmaktır. Örneğin mevcut düğümleri XNodes olarak adlandırın.

Bu nedenle, her XNode için, onu DAG'ye nasıl ekleyeceğinize karar vermeniz gerekir ve zaten DAG'de olma olasılığı vardır.

Bu çok basit sözde koddur. Derleme amaçlı değildir.

DagNode XNode::GetDagNode(Dag dag) {
  if (XNode.IsAssignment) {
    // The assignment is a special case. A common sub expression is not
    // formed by the assignment since it creates a new value.

    // Evaluate the right hand side like normal
    XNode.RightXNode.GetDagNode();  


    // And now take the variable being assigned to out of the current live list
    dag.RemoveDagNodeForVariable(XNode.VariableBeingAssigned);

    // Also remove all DAG sub expressions using the variable - since the new value
    // makes them redundant
    dag.RemoveDagExpressionsUsingVariable(XNode.VariableBeingAssigned);

    // Then make a new variable in the live list in the dag, so that references to
    // the variable later on will see the new dag node instead.
    dag.AddDagNodeForVariable(XNode.VariableBeingAssigned);

  }
  else if (XNode.IsVariable) {
    // A variable node has no child nodes, so you can just proces it directly
    DagNode n = dag.GetDagNodeForVariable(XNode.Variable));
    if (n) XNode.DagNode = n;
    else {
      XNode.DagNode = dag.CreateDagNodeForVariable(XNode.Variable);
    }
    return XNode.DagNode;
  }
  else if (XNode.IsOperator) {
    DagNode leftDagNode = XNode.LeftXNode.GetDagNode(dag);
    DagNode rightDagNode = XNode.RightXNode.GetDagNode(dag);


    // Here you can observe how supplying the operator id and both operands that it
    // looks in the Dags live list to check if this expression is already there. If
    // it is then it returns it and that is how a common sub-expression is formed.
    // This is called an internal node.
    XNode.DagNode = 
      dag.GetOrCreateDagNodeForOperator(XNode.Operator,leftDagNode,RightDagNode) );

    return XNode.DagNode;
  }
}

Yani bu ona bakmanın bir yolu. Ağacın basit bir yürüyüşü ve sadece Dag düğümlerine ekleme yapmak ve ilerlerken bunlara atıfta bulunmak. Örneğin dag'ın kökü, ağacın kökünün döndürdüğü DagNode'dur.

Açıktır ki, örnek prosedür daha küçük parçalara bölünebilir veya sanal işlevlerle alt sınıflar olarak yapılabilir.

Dag'ı tasnif etmeye gelince, her DagNode'dan soldan sağa geçersiniz. Başka bir deyişle, DagNodes sol kenarını ve ardından sağ taraftaki kenarı izleyin. Numaralar ters olarak atanır. Başka bir deyişle, alt öğesi olmayan bir DagNode'a ulaştığınızda, bu Düğüme geçerli sıralama numarasını atayın ve sıralama numarasını artırın, böylece özyineleme sayıların artan sırada atanmasını çözer.

Bu örnek, yalnızca sıfır veya iki çocuğu olan düğümleri olan ağaçları ele almaktadır. Açıkçası bazı ağaçların ikiden fazla çocuğu olan düğümleri var, bu yüzden mantık hala aynı. Sola ve sağa hesaplamak yerine soldan sağa vb. Hesaplayın.

// Most basic DAG topological ordering example.
void DagNode::OrderDAG(int* counter) {
  if (this->AlreadyCounted) return;

  // Count from left to right
  for x = 0 to this->Children.Count-1
    this->Children[x].OrderDag(counter)

  // And finally number the DAG Node here after all
  // the children have been numbered
  this->DAGOrder = *counter;

  // Increment the counter so the caller gets a higher number
  *counter = *counter + 1;

  // Mark as processed so will count again
  this->AlreadyCounted = TRUE;
}

1

Programlamada hangi ağaçların olduğunu biliyorsanız, programlamadaki DAG'ler benzerdir ancak bir düğümün birden fazla ebeveyni olmasına izin verirler. Bu, bir düğümün tek bir ebeveynin altında kümelenmesine izin vermek istediğinizde, ancak döngülerle genel bir grafiğin düğümlü bir karmaşası problemi yaşamadığınız zaman kullanışlı olabilir. Yine de bir DAG'de kolayca gezinebilirsiniz, ancak köke geri dönmenin birden çok yolu vardır (çünkü birden fazla ebeveyn olabilir). Tek bir DAG genel olarak birden fazla köke sahip olabilir, ancak pratikte bir ağaç gibi tek bir köke yapışmak daha iyi olabilir. OOP'de tek ve çoklu kalıtımı anlıyorsanız, ağaç ve DAG'yi bilirsiniz. Bunu zaten burada cevapladım .


1

İsim, tanımı hakkında bilmeniz gerekenlerin çoğunu size söyler: Her kenarın yalnızca bir yönde aktığı bir grafiktir ve bir kenardan aşağı doğru süründüğünüzde yolunuz sizi asla bıraktığınız tepe noktasına geri döndürmez.

Tüm kullanımlar hakkında konuşamıyorum (Wikipedia orada yardımcı oluyor), ancak benim için DAG'ler kaynaklar arasındaki bağımlılıkları belirlerken son derece kullanışlıdır. Örneğin oyun motorum, yüklenen tüm kaynakları (malzemeler, dokular, gölgelendiriciler, düz metin, ayrıştırılmış json vb.) Tek bir DAG olarak temsil eder. Misal:

Materyal, her biri iki gölgelendiriciye ve her gölgelendiricinin bir düz metin gölgelendirici kaynağına ihtiyacı olan N GL programlarıdır. Bu kaynakları bir DAG olarak temsil ederek, yinelenen yükleri önlemek için mevcut kaynaklar için grafiği kolayca sorgulayabilirim. Birkaç malzemenin aynı kaynak koduyla köşe gölgelendiricileri kullanmasını istediğinizi varsayalım. Kaynağı yeniden yüklemek ve mevcut kaynağa yeni bir kenar oluşturduğunuzda her kullanım için gölgelendiricileri yeniden derlemek israftır. Bu şekilde, herhangi bir şeyin bir kaynağa bağlı olup olmadığını belirlemek için grafiği de kullanabilirsiniz ve değilse, onu silebilir ve belleğini boşaltabilirsiniz, aslında bu hemen hemen otomatik olarak gerçekleşir.

Uzantı olarak, DAG'ler veri işleme ardışık düzenlerini ifade etmek için kullanışlıdır. Döngüsel olmayan yapı, aynı tepe noktasını tekrar tekrar karşılaşmadan bir tepe noktasından aşağı doğru işaretçileri takip edebilen bağlamsal işleme kodunu güvenle yazabileceğiniz anlamına gelir. VVVV , Max MSP veya Autodesk Maya'nın düğüm tabanlı arayüzleri gibi görsel programlama dillerinin tümü DAG'lara dayanır.


-5

Yönlendirilmiş çevrimsiz bir grafik, yönlendirilmiş çevrimsiz bir grafiği temsil etmek istediğinizde kullanışlıdır! Kanonik örnek bir aile ağacı veya soy ağacıdır.


Ah, bu da mantıklı. Ama yine de bunun programlama ile ne ilgisi var?
appshare.co

1
Herhangi bir veri yapısının programlama ile ne ilgisi vardır?
Jonathan Feinberg

Tamam anlıyorum. Cevabınızda "veri yapısı" ndan bahsetmemişsinizdir
appshare.co

5
Totoloji! = Açıklama
Eva
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.