Skip to content
Matthew Stern edited this page Mar 29, 2021 · 13 revisions

Topylogic

Welcome to the topylogic-git wiki!

Topylogic is a python library for creating Deterministic and Nondeterministic Finite State Machines (DFA/NFA). But, these DFA's and NFA's aren't truly finite in Topylogic. With Topylogic you can dynamically modify the machine by adding, removing, or even modifying states and transitions while your program is running.

In Topylogic you are also free to begin your program in one or many states that may transition to other states. Thus, Topylogic can either be context-free or context-switching (unthreaded vs threaded).

>>> import topylogic

>>> def vertex_fun(vertex_id, graph, result_vertex, result_edge, vertex_glbl, vertex_edge_vars):

#Do something #Modify result_vertex, result_edge, vertex_glbl, vertex_edge_vars #sumbit a request to the graph return result_vertex, result_edge, vertex_glbl, vertex_edge_vars

>>> def edge_function(id, result_edge, edge_glbl, vertex_from_shared_var, vertex_to_shared_var)

#Do something #Modify edge_glbl return boolean, edge_glbl

>>> g = topylogic.graph() >>> v1 = g.set_vertex(id1, vertex_function, vertex1_variables) >>> v2 = g.set_vertex(id2, another_vertex_function, vertex2_variables) >>> v3 = g.set_vertex(id3, another_different_vertex_function, vertex3_variables) >>> e = g.set_edge(id1, id2, edge_function, edge1_variables) >>> bi_e = g.set_bi_edge(id2, id3, another_edge_function, edge2_variables) >>> vr = topylogic.vertex_result(vertex_var, edge_var) >>> g.set_starting_vertex(id1) #g.set_starting_vertices([id1]) >>> g.run_one(vr) #g.run([vr]) >>> g.destroy()

Basic Usage

The basic implementation of Topylogic uses topylogic.SINGLE. In this mode you will create a graph with many vertices and many edges. When you call g.set_starting_ids you pass an array of one integer and then you call g.run with an array containing one vertex_result.

When g.run is called the graph will start by executing the vertex_function of the requested id in the starting set. The graph will then sequentially determine the next transition and execute the next vertex, one vertex at a time. There is no threading.

Example :

g->vertices = [v1, v2, v3, v4]

edge = {v1->v2, v1->v3, v2 <-> v3, v3->v4, v4->v1}

Start = v1

Suppose the edges always return true and that the edge between v1 and v2 is checked before v1 and v3, and the edge between v3 and v2 is checked before v3 and v4.

Execution :

v1 -> v2 -> v3 -> v2 -> v3 ....

=========
Advanced Usage

Instead of using SINGLE you may use topylogic.SWITCH, topylogic.SWITCH_UNSAFE, topylogic.NONE, and topylogic.NONE_UNSAFE. These modes now give to a threaded system. The mode NONE is like SINGLE, but you can start at multiple vertices. For instance take the example above but start at v1 and v4.

Execution :

v1 -> v2 -> v3 -> v2 -> v3 ....
v4 -> v1 -> v2 -> v3 -> v2 ....

The mode SWITCH on the other hand will instead evaluate all edges and will create new threads for every vertex transitioned to.

Execution :

v1 -> v2 -> v3 -> v2 ...
            |  -> v4 ...
|  -> v3 -> v2 -> v3 ...
      |  -> v4 -> v1 ...
v4 -> v1 -> v2 -> v3 ...
      |  -> v3 -> v2 ...
            |  -> v4 ...

The _UNSAFE means if in the edge_function if vertex_to_shared_var parameter is None or the value of the vertices shared variables. The reason it is None for safety is to avoid reading the variable while the other vertex is writing to it.

How are DFA's and NFA's implemented?
In Topylogic we define Vertices to be States and Edges to be state transitions. The DFA or NFA in Topylogic is known as the Graph.

The Graph contains all of the information in the program.

* Is it threaded?
  • What do we do when a thread won't spawn?
  • Do we make a new thread on state transition?
* What information should be saved?
  • How often should the information be saved?
* What are the vertices?
* What is the current state of the machine?
  • What should be executed?
* What are the variables that should be passed to each Vertex?
* Should it kill a vertex that is ran a certain number of times?
  • Should it stop after a certain number of steps?

The Vertex contains information about what the state means and where to transition to.

* What are the edges?
* What are it's variables?
* What variables does it share with it's edges?
  • What function does it execute?

The Edges contains information about itself and a path.

* What vertex initiated it?
* What vertex does it point to?
* What are it's variables?
  • What function does it execute?
Once put all together, the Graph starts at some vertices, which do something, and then figures out how to transition.

To transition, the edge functions must be invoked. Should an edge return True, then the Graph will call the vertex that the edge is connected to next. Of course, depending on mode, either the first edge to return True is chosen, or all edges to return True are called.

The graph has a basic loop

#. Run the initial set of vertices
#. Check the edges and determine next set
#. Process requests
#. Print information
  1. Check if termination conditions are met and stop if so, else run next set of vertices and repeat
=========
Requests

Requests are made mostly for thread safe purposes. Should a program be threaded and client wants to edit some vertex it may be unsafe, should that vertex also be active. Instead Requests are made so that the client can create a list of desired tasks to be executed once all current vertices are completed. Requests can also be used in the case that the client just wants some external function to be called after the execution of the vertices.

Printing

After requests are completed the program will print information to a JSON file. The program may print only on the first and last state ran of the graph, every state, or no state (no printing). The program can also save very brief or verbose in printing. Printing is only for the interest of the user, and is not needed.

Clone this wiki locally