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.
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.
Yanıtlar:
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.
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
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:
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.
Ç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.
Yönlendirilmiş Asiklik Grafikler (DAG), onları diğer grafiklerden ayıran aşağıdaki özelliklere sahiptir:
Ş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.
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:
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
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.
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ı, ...
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;
}
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 .
İ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.
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.