2009-03-14 3 views
21

Ich möchte eine Knoten-Schnittstelle implementieren, ein im Grunde DAG wobei jeder Knoten auf es Eingangsanschlüsse eine Operation durchführt, und gibt etwas (die Sie an einen anderen Knoten verbinden kann)Implementierung einer node-basierten grafischen Oberfläche?

Einige Beispielanwendungen:


Als erstes Ziel, würde Ich mag eine grafische Anwendung mit nur zwei Knoten haben. Eine "Nummer", die einfach eine feste Zahl ausgibt, und ein "Add" -Knoten, der zwei Eingaben nimmt und die Summe der beiden ausgibt.

Da die Menschen so weit beantwortet haben, ich habe eine ungefähre Vorstellung davon, wie die Daten in Code repräsentieren, zum Beispiel in Python'y suchen Pseudo-Code:

class Number: 
    def __init__(self, value): 
     self.value = value 

    def eval(self): 
     return self.value 

class Add: 
    def __init__(self, input1, input2): 
     self.input1 = input1 
     self.input2 = input2 

    def eval(self): 
     return self.input1.eval() + self.input2.eval() 


a = Number(20) 
b = Number(72) 

adder = Add(a, b) 
print adder.eval() 

Wie würde ich über Verpackung bekam eine benutzerdefinierte GUI um dies? Etwas wie das Folgende, aber etwas weniger von Hand gezeichnet!

nodal UI mockup

Wo soll ich anfangen? Ich plane derzeit, es in Objective-C/Cocoa zu schreiben, obwohl ich mehr als offen für Vorschläge für andere Sprachen bin.

Antwort

4

Ich würde damit beginnen, einige grundlegende Schnittstellen zu modellieren (im OOP-Sinn, nicht im GUI-Sinn). Es scheint mir, dass Sie einen Knoten haben werden, der eine Sammlung von Eingaben und eine einzige Ausgabe akzeptiert. Sie haben keinen Hinweis darauf gegeben, wie breit die Datentypen sind, aber Sie werden eine geeignete Methode für die Darstellung Ihrer Eingaben/Ausgaben wünschen. Für Ihr erstes Ziel könnte dies eine Ganzzahl sein.

In einiger generischen OOP-Sprache C-Stils (hoffen, dass es Sinn macht):

class Node<T> { 
    Node<T>[] inputs; 
    T eval(); 
} 

class AdderNode extends Node<int> { 
    int eval() { 
     int accum = 0; 
     for (inputs : i) 
      accum += i.eval(); 
     return i; 
    } 
} 

class ConstNode<int I> extends Node<int> { 
    int eval() { return I; } 
} 

AdderNode a; 
a.inputs.add(ConstNode<2>()); 
a.inputs.add(ConstNode<3>()); 
a.eval(); 

Sie auf dem durch Ersetzen int mit einer abstrakten Klasse, generisch, oder Schnittstelle erweitern können. Die tatsächliche Implementierung hängt natürlich von der Sprache ab.

1

Ich würde mit der Modellierung der interessanten Operationen beginnen. Letztendlich werden Sie sie mit einem UI verbinden, aber das ist das Lenkrad und Gaspedal, nicht der Motor.

Was Sie zu erstellen versuchen, hat viele Gemeinsamkeiten mit Programmiersprachen: Variablen, Werte, Typen, Ausdrücke, Bewertung, usw. Viele der Metaphern sind anwendbar und könnten einige Hinweise geben. Wenn Sie .NET 3.5 verwenden, haben Sie die Option Expression Trees, mit der Sie Codeausdrücke zur Laufzeit darstellen und kompilieren können.

Zum Beispiel Ihr erstes Ziel zu modellieren:

using System.Linq.Expressions; 

ConstantExpression theNumber2 = Expression.Constant(2); 
ConstantExpression theNumber3 = Expression.Constant(3); 

BinaryExpression add2And3 = Expression.Add(theNumber2, theNumber3); 

den Ausdruck aufzurufen, müssen wir add2And3 mit einem Verfahren wickeln. Dies wird mit einem Lambda-Ausdruck durchgeführt:

Expression<Func<int>> add2And3Lambda = Expression.Lambda<Func<int>>(add2And3); 

Func<int> eine Methode darstellt, die keine Parameter annimmt und gibt eine int. In C#, die durch add2And3Lambda vertreten Code wäre:

() => 2 + 3 

Also, was wir haben, ist ein Ausdruck Baum, dessen Wurzel ist eine Methode. Da ein Verfahren aufrufbar ist, können wir den Baum in eine Instanz des zugrunde liegenden Delegattyp kompilieren:

Func<int> add2And3Func = add2And3Lambda.Compile(); 

Jetzt können wir den Code rufen wir gebaut:

int theNumber5 = add2And3Func(); 

Jeder Ausdruck zur Verfügung. NET-Sprachen werden unterstützt.

Stellen Sie sich vor, jeder Knoten in Ihrem Diagramm hat eine Expression damit verbunden. Das könnte Ihnen eine Vorstellung von der Kraft der Ausdrucksbäume vermitteln und Ihnen zeigen, wie sie Ihnen bei dieser Aufgabe helfen können.

1

Allen Knoten-Systemen ist gemeinsam, dass sie eine funktionale Programmiersprache beschreiben. Eine Funktion benötigt mehrere Parameter und gibt unabhängig davon, zu welchem ​​Zweck sie erstellt wurde, ein einzelnes Ergebnis zurück. Einige Beispiele:

  • Grafik: Blur (Bild, Kernel, Radius) -> Bild

  • Math: Hinzufügen (Anzahl, Nummer) -> Anzahl

  • Relational: Filter (Tabelle, predicate) -> Tabelle

im Grunde, dass kommt zu einer Funktionssignatur wie Func<object[], object> (C#).

Sie werden mit der Frage konfrontiert, wie Sie Ihr Knotensystem persistent machen können. Möchten Sie das Ergebnis eines Knotens als Parameter nur für einen anderen Knoten (Baum) oder mehrere Knoten (Graph) nutzbar machen?

Beispiel eines Baumes, haben direkt die Parameter ein Kind Knoten:

Add(
    Multiply(
    Constant(5), 
    Constant(4) 
), 
    Multiply(
    Constant(5), 
    Constant(3) 
) 
) 

Beispiel eines Graphen, speichern Sie alle Knoten in einer Liste und nur Referenzen verwenden:

A := Constant(5) 
B := Constant(4) 
C := Constant(3) 

D := Func(Multiply, A, B) 
E := Func(Multiply, A, C) 

F := Func(Add, D, E) 
0

Vielleicht bwise hat etwas von Interesse?

Auf der unteren Hälfte der this page zeigt ein Beispiel der Verwendung von bwise, um einen Multiplikationsblock zu erstellen, der zwei Zahlen als Eingabe nimmt.

1

ich auf die Implementierung einer solchen Schnittstelle in Cocoa einige nützliche Informationen gefunden:

0

Ich implementierte eine Execution Graph wie Sie in diesem Projekt beschreiben: GRSFramework

Der Quellcode here gefunden werden kann.

Derzeit arbeite ich an der Freigabe einer besseren, gereinigten Version dieses Systems im Projekt ExecutionGraph.
Es könnte auch für Sie interessant sein.

Dann gibt es auch die TensorFlow Bibliothek von Google, die ein ähnliches System TensorFlow

0

ich auf diesen Thread gestolpert umgesetzt hat, während für eine ähnliche Lösung zu erforschen. Vor kurzem fand ich ein nettes Projekt auf GitHub https://github.com/nodebox/nodebox , die genau zu sein scheint, was Sie suchen. Mindestens einer könnte die Editor-Komponenten aus dem Projekt extrahieren und übernehmen.

Grüße, Stephan

+0

Willkommen bei Stackoverflow, Dank für den Wunsch, mit Links zu tragen, aber Antworten nur abgeraten werden. Bitte lesen Sie die [Antwortrichtlinien] (https://stackoverflow.com/help/how-to-answer). Eine gute Faustregel ist, Ihre Antwort ohne den Link zu betrachten, und wenn sie wenig bis keinen Wert bietet, sollten Sie eine Erweiterung in Erwägung ziehen. – JaredMcAteer

Verwandte Themen