Welcome to SYGA Docs
To get your hands dirty with SYGA, visit www.syga.space
Getting started
Hello, world
Let's get started by running some hello world code! Enter the following code into the editor and build.
text = 'hello, stranger!'
G = engine.DiGraph([(i + 1, i + 2) for i in range(len(text) - 1)])
G.color_edges_by(lambda u, v, G: v if 'label' in G.nodes[v] else None)
G.color_nodes_by(lambda v, G: v if 'label' in G.nodes[v] else None)
G.label_nodes_by(lambda v, G: G.nodes[v]['label'] if 'label' in G.nodes[v] else ' ')
for i, symbol in enumerate(text):
G.nodes[(i + 1)]['label'] = symbol
print(text)
You should see a visualization.
Structure of a SYGA program
Let us break down the code above. A SYGA program has two parts - setup and algorithm. In setup, you decide - Whether the graph is directed - What edges and nodes it has - The logic for coloring nodes and edges - The logic for labelling nodes and edges
You do this by initializing and calling methods of an instance of either engine.Graph or engine.DiGraph.
G = engine.DiGraph([(i + 1, i + 2) for i in range(len(text) - 1)])
As observed above, you can pass a list of tuples in order to initialize the graph.
Then we do the coloring, labelling and shaping.
G.color_edges_by(lambda u, v, G: v if 'label' in G.nodes[v] else None,)
G.color_nodes_by(lambda v, G: v if 'label' in G.nodes[v] else None)
G.label_nodes_by(lambda v, G: G.nodes[v]['label'] if 'label' in G.nodes[v] else ' ')
The API is the similar for all 3. You call a method of G such as G.color_nodes_by and G.color_edges_by.
API overview
In essence, all color_*_by, label_*_by and shape_*_by take some instruction on how to transform each edge or node between each tick(line of code that runs). In these instructions, we can either specify the range of colors to be visualized ourselves or we can leave it up to SYGA to infer it.
There are 3 ways to pass these instructions to SYGA.
Let us demonstrate this by G.color_nodes_by.
collection
discovered = list()
... some other code
G.color_nodes_by(discovered)
... some other code
for i, symbol in enumerate(text):
discovered.append(i+1)
G.color_nodes_by(discovered, color="green")
lambda
G.color_nodes_by(lambda v, G: v if 'label' in G.nodes[v] else None)
G.color_nodes_by(lambda v, G: v if 'label' in G.nodes[v] else None, color="red")
props
The graph we created using engine.Graph or engine.DiGraph has 2 properties nodes and edges that we can leverage. These properties track an instance for each vertex and edge we initialized. It is possible to assign custom properties to these instances and have the coloring logic depend on these properties.
For instance, if we initialize in the beginning
for v in G.nodes:
G.nodes[v]['discovered'] = False
It is possible to color the nodes by whether this is true.
G.color_nodes_by(prop='discovered')
G.color_nodes_by(prop='discovered', color="red")
Conclusion
As a final note, we can specify the color for when the condition is false by passing an array.
G.color_nodes_by(prop='discovered', color=["green", "blue"])
Now nodes will start green and will turn red as they are discovered.
You may have noticed that in all of the above examples, we visualized only scenarios with 2 colors. Algorithms may require scenarios where we have at least 3 states for nodes/edges.(Such as Dijkstra with OPEN, CLOSED and UNKNOWN).
The documentation for how to write this case is still in-progress.