From: Thomas Walker Lynch Date: Mon, 30 Dec 2024 12:43:13 +0000 (+0000) Subject: adding support for umbounded graphs X-Git-Url: https://git.reasoningtechnology.com/usr/lib/python2.7/encodings/aliases.py?a=commitdiff_plain;h=c9f24a1802e0eb8e588d55a6bc84ee2363179753;p=Ariadne adding support for umbounded graphs --- diff --git a/README.txt b/README.txt index 5e7234b..2399ef0 100644 --- a/README.txt +++ b/README.txt @@ -7,99 +7,22 @@ Note the directories: Ariadne/document🖉, Ariadne/developer/document🖉, and -------------------------------------------------------------------------------- Ariadne -Ariadne is a graph based build tool. +When you are tasked with a project build that is as complex as Daedalus's impossible to solve maze, modern Ariadne hands you a piece of chalk to draw arrows with. She has had a lot of time to think about it, and chalk works even better than a ball of string. -When you are tasked with a project build that is as complex as Daedalus's impossible to solve maze, modern Ariadne hands you a piece of chalk to draw arrows with. It works even better than a ball of string. +Ariadne is an directed graph based build tool. The tool and its configuration file are written in Java. We don't brag about this, rather this is the environment for which it came to fruition. Other language versions will surely follow, hence the source code directory is called javac🖉 and it builds to a scratchpad directory. -A tool like Ariadne is useful for projects that have compiled languages, where there are many steps in getting from source code to a loadable set of instructions. At is able to handle complex cases with generation of sources from ANTLR grammars, and the implied dependencies of Java programs. +Ariadne was developed to be used in a large project research environment where code is synthesized, not all of the code is working at any one time, and there are many steps for getting from authored content to loadable machine code. -Ariadne can also be used to describe dependencies on libraries or other programs used by a given program. This is useful with both compiled and interpreted languages. - -In the Java implementation of Ariadne, everything is coded in Java, including the developer's description of the dependency graph. +Ariadne will also be helpful for compiled language projects, such as C, C++. Ariadne can also be used to describe dependencies on libraries or other programs so it will be useful with interpreted languages also. If a developer were to compare `Ariadne` with `make`, the file corresponding to the 'make file' is a dynamically loaded Java program known as the 'graph definition'. Whereas a make file for a complex project will contain a lot of shell code, the Ariadne graph definition is all Java code. Where a make file has 'pattern rules' Ariadne will typically has regular expressions. Make can not backwards chain through pattern rules, Ariadne can. Ariadne is more procedural than Maven, which is more descriptive. Ariadne allows for finer grain description of dependencies and finer grain decision making than with Gradle task dependencies. -------------------------------------------------------------------------------- -General Comments about Graphs - -Conceptually a graph is a set with two members, nodes and edges, both also being sets. In turn, each edge is a pair of nodes. In a directed graph, one of the nodes of such a pair is said to be the tail, while the other is said to be the head. - -A leaf node is unusual in that it is not the tail of any edge. - -When a node is selected, a set is implied that contains each and every edge that has the selected node as its tail, if any. These are the outgoing edges for the selected node. Each outgoing edge then has a head. We say that the set of head nodes are distance one from the selected node. (The selected node itself is at distance zero.) Distance one nodes are said to be 'neighbor' nodes. - -Deterministic traversal is an algorithm that is given two arguments when it is started, a graph definition, and a start node. The start node is then assigned to a state variable. At each step of the algorithm, the node in the state variable is selected on the graph, then the state variable is re-assigned to be one of the distance one nodes. - -Deterministic search for a node is an example of an algorithm that makes use of traversal. Deterministic search begins with a graph, a start node, a predicate that is said to recognize the searched for node, and a function that guides the traversal. - -A self cycle in a graph consists of a node and an edge, where said edge has the node as both its tail and its head. There is no change in the traversal state variable when taking a traversal step through such an edge. In general, a cycle consists of a start node and all nodes and edges traversed up until arriving back at said start node. - -It is a bad thing to have cycles in a build graph, as cycles will correspond to circular dependencies. Hence Ariadne looks for these and reports them. - --------------------------------------------------------------------------------- -The Ariadne Build Graph - -An Ariadne graph definition contains a 'graph definition function' list. A graph definition function is given a node label, and returns a node, or null if it can not find a node with such a label. A common graph definition function contains a map where each entry is a node label and a node. - -An Ariadne node is dictionary that maps a string key to a value. The type of the value is implied by the string key. Depending on the Ariadne tool being used, each node map will typically have entries for the keys "label", "build", and "neighbor". - -A "label" value is a string that is unique among the nodes in the graph. The "build" value is a function that a build tool will call when a file corresponding to a node is to be built. The "neighbor" value is a list of neighbor nodes. - -The Ariadne graph definition is optimized to be a run time data structure used for traversal, so the neighbor list is held directly in the node. Also, there is only one edge property, that of 'dependency'. As a consequence, there is no need for a separate edge table. - --------------------------------------------------------------------------------- -Ariadne Build Tool - -For the default Ariadne build tool, each node label is either symbolic, or is a file path. The tool descends into the graph, based on file modification dates, and builds nodes that are modified less recently than their dependencies. - --------------------------------------------------------------------------------- -For Developers/Testers - -The project has three entry points, one for each project role: developer, tester, and administrator. To enter the project, source the environment appropriate for the role, either `env_developer`, `env_tester`, or `env_administrator`. - -1. Production - - 1.1. development - - cd Ariadne - . env_developer - - [do work] - - make - release - - 1.2 regression testing - - cd Ariadne - . env_tester - make - run - -2. Debugging - - cd Ariadne - . env_developer - make - # puts links to source files on the `scratchpad` - gather_source_links - - [change to tester module] - - cd Ariadne - # the developer parameter links in the actual source in the developer module - . env_tester developer - make - run - -The `make` command you see above is a bash script. Version 1.0 of Ariadne uses a direct 'build it all every time' approach. Perhaps in version 2.0 or so, we will use a prior version of Ariadne for the build environment. - -In IntelliJ IDEA there are two modules, developer and tester. The output for each module is 'scratchpad' tests are added through the `run edit-configuration` menu. See tool_shared/third_party/document🖉 directory for more information. - -Using Ariadne -------------- - -After it is built and released the tool will appear in the Ariadne/release directory where it can be regression tested or imported into another project. +See also: +~RT-project-share/documents🖉 for information about RT projects. +~Ariadne/documents🖉 for more general information about Ariadne +~Ariadne/developer/documents🖉 specific information about the code +~Ariadne/tester/documents🖉 specific information about the tests diff --git a/developer/deprecated/Build.javax b/developer/deprecated/Build.javax new file mode 100644 index 0000000..b0cdab3 --- /dev/null +++ b/developer/deprecated/Build.javax @@ -0,0 +1,76 @@ +import java.util.List; + +public class Build { + + // Function to load the graph class dynamically + public static Class includeAClass(String aClassFp) { + ClassLoader classLoader = Build.class.getClassLoader(); + String className = aClassFp.replace('/', '.').replace(".class", ""); + try { + return classLoader.loadClass(className); + } catch (Exception e) { + System.out.println("Error loading class '" + className + "': " + e.getMessage()); + return null; + } + } + + // Build function + public static void build(String graphDefinitionFp, List rootNodeLabels) { + // Print summary of what we are doing + System.out.println("build:: Building targets for graph '" + graphDefinitionFp + ".class'"); + if (rootNodeLabels.isEmpty()) { + System.out.println("No build targets specified. Please provide root node labels to build."); + System.exit(0); + } + System.out.println("Building targets: " + String.join(", ", rootNodeLabels)); + + // Load the dependency graph class from arg[1] + Class graphDefinitionClass = includeAClass(graphDefinitionFp); + if (graphDefinitionClass != null) { + System.out.println("build:: loaded " + graphDefinitionFp + ".class"); + } else { + System.out.println("build:: failed to load " + graphDefinitionFp + ".class"); + System.exit(1); + } + + // Get the node_map and node_f_list from the graph class + // Assuming these methods are static and return the appropriate types + // Replace with actual method calls if they are different + Object nodeMap = null; + Object nodeFList = null; + try { + nodeMap = graphDefinitionClass.getMethod("getNodeMap").invoke(null); + nodeFList = graphDefinitionClass.getMethod("getNodeFList").invoke(null); + } catch (Exception e) { + System.out.println("Error invoking methods on graphDefinitionClass: " + e.getMessage()); + System.exit(1); + } + System.out.println("node_map: " + nodeMap); + System.out.println("node_f_list: " + nodeFList); + + // Create an instance of AriadneGraph, and run the build scripts + // Assuming AriadneGraph has a constructor that takes nodeMap and nodeFList + // Replace with actual constructor call if it is different + try { + Class ariadneGraphClass = Class.forName("AriadneGraph"); + Object graph = ariadneGraphClass.getConstructor(nodeMap.getClass(), nodeFList.getClass()).newInstance(nodeMap, nodeFList); + ariadneGraphClass.getMethod("runBuildScriptsF", List.class).invoke(graph, rootNodeLabels); + } catch (Exception e) { + System.out.println("Error creating or invoking AriadneGraph: " + e.getMessage()); + System.exit(1); + } + } + + // Entry point when run as a script + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Usage: ./build [root_node_labels...]"); + System.exit(1); + } + + // Get graph definition file and root node labels + String graphDefinitionFp = args[0]; + List rootNodeLabels = args.length > 1 ? List.of(args).subList(1, args.length) : List.of(); + build(graphDefinitionFp, rootNodeLabels); + } +} diff --git "a/developer/document\360\237\226\211/DirectedGraph_cycle_algorithm.txt" "b/developer/document\360\237\226\211/DirectedGraph_cycle_algorithm.txt" new file mode 100644 index 0000000..7a202e2 --- /dev/null +++ "b/developer/document\360\237\226\211/DirectedGraph_cycle_algorithm.txt" @@ -0,0 +1,84 @@ + /*-------------------------------------------------------------------------------- + Interface + + 1. nodes are referenced by label. + + 2. A list is a kind of sequence. It consists of a leftmost item, subsequent + items, and a rightmost item. + + 3. A node list consists of a leftmost node, subsequent nodes, and a rightmost node. + + 4. `path_stack` + + The `path_stack` is a list. Each item in the stack is a node list. + + The rightmost items is the top of the stack. + + The leftmost item is a list of root nodes, where traversal of the graph + starts. + + Given two adjacent items on the path stack, say e0 and e1: + + Say k0 is the leftmost node on the node list e0. + + The e1 will be the neighbor (child) list from node k0. + + Hence, the path stack consists of the child lists of nodes along + a traversal. We chose a leftmost traversal. + + e0: k_0 k_1 ... k_2 + + e1: k_0_0 k_0_1 ... k_0_2 ; children of k_0 + + e2: K_0_0_0 k_0_0_1 ... k_0_0_2 ; children of k_0_0 + + + 5. `path` + + A list of the leftmost nodes from a path stack. + + Given that e0 is a root node, `path` will consist of + + k_0, k_0_0, k_0_0_0 ... k_0_0..._0 + + Within the context of a path, k_0 is the leftmost item, and k_n is the + rightmost item. + + + 6. removing a cycle + + This is a build tool. Each node corresponds to a build objective, and the + neighbor nodes are dependencies. A neighbor node is a child node in our + tree descent, and is a dependency to our build tool. + + This routine is called as part of the analysis phase. Nothing is + built here, rather we are merely marking dependency cycles that we + find when descending from the root nodes. + + When we find a cycle, we remove those nodes from the current traversal + path, because we do not went the analysis to do in circles. It is + possible that there are spurs that emanate from the cycle, and following + these might lead to finding more cycles. + + Our build tool (which is not in this file) will stop descending through + the graph upon finding a cycle, and the effects of this will cause + upstream nodes to also not be built. Hence, the cycles hidden behind + other cycles are irrelevant. + + However, if we want to make routine of more general use, then the + discovered cycles should be pushed on to a cycle stack, and then each + item on the cycle stack would be used as root nodes for a new cycle + search. Note the leftmost cycle on each recursive search on the leftmost + node, will be the original cycle. + */ + + /* + Given a path to a node in the graph, `left_path`. + + Checks if the rightmost node (referenced by label) recurs earlier in the path. + Presumably the rightmost node has been recently appended to the path. + + If there is no cycle, returns null, otherwise returns the interval [i ,n], + of indexes into the path where the cycle is found. `n` will always be + the index of the rightmost node in the path list. + */ diff --git "a/developer/document\360\237\226\211/DirectedGraph_definition.txt" "b/developer/document\360\237\226\211/DirectedGraph_definition.txt" new file mode 100644 index 0000000..9f17927 --- /dev/null +++ "b/developer/document\360\237\226\211/DirectedGraph_definition.txt" @@ -0,0 +1,26 @@ + +To create a directed graph, extend the class `Ariadne_DirectedGraph`. + +In Ariadne a graph is defined by the `start` and `lookup` functions. + +`start` returns a list of start nodes. We require that `start` returns +the same list of nodes, no matter when it is called. It + + + + + +The graph is not wellformed if `start` returns a label that `lookup` fails to find. + +`lookup` is a function. It accepts a node label, and returns the node that has that label. A possible implementation of `lookup` is to lookup the node in a map, but there are many other possible implementations. + +Because lookup is a function who's definition is left to the user, it is not possible in general to analyze `lookup` to know which nodes are in the graph. Even when `lookup` has a definition that is analyzable in theory, it is typically not practical to analyze it to discover the possible node labels. Hence, the user also provides the build tool with a list of possible `start` labels, where graph traversal can start. + +After extending `Ariadne_DirectedGraph` the user might want to structure `lookup` by calling a number of helper functions. These helper functions play the same role as do separate make file rules when using `make`. + + + + + + + diff --git "a/developer/document\360\237\226\211/GraphDirectedAcyclic_1.txt" "b/developer/document\360\237\226\211/GraphDirectedAcyclic_1.txt" deleted file mode 100644 index 7a202e2..0000000 --- "a/developer/document\360\237\226\211/GraphDirectedAcyclic_1.txt" +++ /dev/null @@ -1,84 +0,0 @@ - /*-------------------------------------------------------------------------------- - Interface - - 1. nodes are referenced by label. - - 2. A list is a kind of sequence. It consists of a leftmost item, subsequent - items, and a rightmost item. - - 3. A node list consists of a leftmost node, subsequent nodes, and a rightmost node. - - 4. `path_stack` - - The `path_stack` is a list. Each item in the stack is a node list. - - The rightmost items is the top of the stack. - - The leftmost item is a list of root nodes, where traversal of the graph - starts. - - Given two adjacent items on the path stack, say e0 and e1: - - Say k0 is the leftmost node on the node list e0. - - The e1 will be the neighbor (child) list from node k0. - - Hence, the path stack consists of the child lists of nodes along - a traversal. We chose a leftmost traversal. - - e0: k_0 k_1 ... k_2 - - e1: k_0_0 k_0_1 ... k_0_2 ; children of k_0 - - e2: K_0_0_0 k_0_0_1 ... k_0_0_2 ; children of k_0_0 - - - 5. `path` - - A list of the leftmost nodes from a path stack. - - Given that e0 is a root node, `path` will consist of - - k_0, k_0_0, k_0_0_0 ... k_0_0..._0 - - Within the context of a path, k_0 is the leftmost item, and k_n is the - rightmost item. - - - 6. removing a cycle - - This is a build tool. Each node corresponds to a build objective, and the - neighbor nodes are dependencies. A neighbor node is a child node in our - tree descent, and is a dependency to our build tool. - - This routine is called as part of the analysis phase. Nothing is - built here, rather we are merely marking dependency cycles that we - find when descending from the root nodes. - - When we find a cycle, we remove those nodes from the current traversal - path, because we do not went the analysis to do in circles. It is - possible that there are spurs that emanate from the cycle, and following - these might lead to finding more cycles. - - Our build tool (which is not in this file) will stop descending through - the graph upon finding a cycle, and the effects of this will cause - upstream nodes to also not be built. Hence, the cycles hidden behind - other cycles are irrelevant. - - However, if we want to make routine of more general use, then the - discovered cycles should be pushed on to a cycle stack, and then each - item on the cycle stack would be used as root nodes for a new cycle - search. Note the leftmost cycle on each recursive search on the leftmost - node, will be the original cycle. - */ - - /* - Given a path to a node in the graph, `left_path`. - - Checks if the rightmost node (referenced by label) recurs earlier in the path. - Presumably the rightmost node has been recently appended to the path. - - If there is no cycle, returns null, otherwise returns the interval [i ,n], - of indexes into the path where the cycle is found. `n` will always be - the index of the rightmost node in the path list. - */ diff --git "a/developer/document\360\237\226\211/dependency_graph.html" "b/developer/document\360\237\226\211/dependency_graph.html" deleted file mode 100644 index a728d42..0000000 --- "a/developer/document\360\237\226\211/dependency_graph.html" +++ /dev/null @@ -1,151 +0,0 @@ - - - - Class and mature functions reference - - - - -
- - A very rough first draft of a reference to the classes. - -

Cycle Detection on a Dependency Graph

-

Overview

- -

A Dependency Graph: Is a directed acyclic graph - where non-leaf nodes are build targets, which are either symbolic, or - correspond to files in the file system. Leave nodes correspond to files - in the file system, and the only edge property is 'dependency'.

- -

Functions

- -

1. is_acyclic_q

-

- Purpose: To determine if the dependency graph is acyclovir. -

-

- Parameters: -

    -
  • root_node_labels: A list of labels for the root nodes to start the cycle search.
  • -
  • verbose: A boolean flag for enabling detailed output (default is true).
  • -
-

-

- Returns: -

    -
  • 'acyclic' if no cycles are found.
  • -
  • 'cycle_found' if cycles are detected.
  • -
-

-

- Process: -

    -
  • Initializes a stack for DFS traversal.
  • -
  • Iteratively calls the is_acyclic_q_descend function to traverse the graph and detect cycles.
  • -
  • Updates the traversal state and continues exploring other paths until the stack is empty.
  • -
-

-

2. is_acyclic_q_descend

-

- Purpose: To perform the actual DFS traversal and cycle detection for a given path. -

-

- Parameters: -

    -
  • path_stack: A stack representing the current path in the graph.
  • -
  • verbose: A boolean flag for enabling detailed output (default is true).
  • -
-

-

- Returns: -

    -
  • 'leaf_node' if the current node has no children.
  • -
  • 'cycle_found' if a cycle is detected.
  • -
-

-

- Process: -

    -
  • Collects the current path and node.
  • -
  • Checks for cycles by comparing the current node with nodes in the path.
  • -
  • Marks nodes involved in cycles and updates the stack to continue traversal.
  • -
-

-

Usage

-

- The is_acyclic_q function is used to ensure that the dependency graph defined in the build file is free of cycles. This is crucial for preventing infinite loops and ensuring that the build process can proceed smoothly. -

-
- - - diff --git "a/developer/document\360\237\226\211/graph_print.html" "b/developer/document\360\237\226\211/graph_print.html" new file mode 100644 index 0000000..039ebc8 --- /dev/null +++ "b/developer/document\360\237\226\211/graph_print.html" @@ -0,0 +1,327 @@ + + + + + + + Tree Shell-Based Printout + + + +
+
+

Tree Shell-Based Printout

+

Exploring the systematic traversal and printing of unbounded trees using shell concepts.

+
+ +

Introduction

+ +

The Ariadne Graph is generated from the `lookup` function. Hence for any traversal of the graph, we can not know the dimensions of the traversal tree. It can even be unbounded in depth or number of nodes at a given depth, i.e. breadth. This makes it challenging to print the graph.

+ +

Grid Traversal Techniques

+ +

Diagonal Shell Traversal

+

A two dimensional grid is also open in two dimensions, but it can be reduced to a linear enumeration by viewing the quarter plain as a stack of + diagonal shells.

+
n = x + y
+

Points are then traversed shell-by-shell, starting from the top-left corner. For example:

+

(0,0), (0,1), (1,0), (2,0), (1,1), (0,2), ...

+ +

Rectangular Shell Traversal

+

An variation of the diagonal shell approach is the rectangular shell traversal, where shells cover all points within a rectangle defined by:

+
max(x, y) = n
+

Rectangular Shell Traversal fills out the n by n grid at each step. For example:

+
    +
  • Rectangular shell n=0: (0,0)
  • +
  • Rectangular shell n=1: (0,1), (1,0), (1,1)
  • +
  • Rectangular shell n=2: (0,2), (1,2), (2,2), (2,1), (2,0)
  • +
+ +

Mapping Trees to a Grid

+ +

A node in a tree can also be given two co-ordinates, that of its depth + in the tree, and the node count from the left at that depth, which we + call its breadth, giving coordinates (d, b):

+ +

Then nodes on diagonal shell n satisfy the condition:

+
d + b = n
+ +

While those on rectangle shell n satisfy:

+
max(d, b) = n
+ + +

Missing Topology

+ +

On a two dimensional grid, each point has four distance one neighbors. when the grid nodes are enumerated on shells, each point will have two neighbors; however, we if need be, the other two neighbors can be identified through functions of the index into the enumeration.

+ +

When the nodes on the tree are enumerated, the parent connection information is lost. As each node in the tree can have a different number of children, we can not compute this information from the enumeration index. However, node labels in the graph are unique, so we can annotate each + node in the enumeration with the name of its parent.

+ +

However, such annotations will not always reference nodes that have already been visited in the enumeration. I.e the enumeration does not + preserve forward referencing of parent nodes annotations.

+ +

Example

+

Consider this tree, subscripts being (d,b):

+

+                A(0,0)
+           /   /      \    \
+    B(1,0)  C(1,1)  D(1,2)  E(1,3)
+                           /  |   \
+                      F(2,0) G(2,1) H(2,2)
+  
+ +

If printed successive rectangular shell per line:

+
    +
  • n=0: A
  • +
  • n=1: B(A) C(A)
  • +
  • n=2: D(A) F(E) G(E) H(E) +
  • n=3: E(A) +
+ +

In this scenario, nodes like E(D), F(D), and G(D) reference their + parent D(A), but D(A) is found on the same line. If lower d values + are printed first, then

+ +

The same example using diagonal shells

+ +

Traversal using diagonal shells would produce the following order:

+
    +
  • n=0: A
  • +
  • n=1: B(A)
  • +
  • n=2: C(A) F(E)
  • +
  • n=3: D(A) G(E)
  • +
  • n=4: E(A) H(E)
  • +
+

Note that on shell 3, G references parent E which is on shell 4.

+ +

Another Example

+ +

+         A
+      /  |  \
+     B   C   D
+    /|    \
+   E F     G
+         /   \
+        H     I
+  
+ +

The following grid representation provides a structured view of the tree following the rectangular shell approach. When n is incremented, the grid can grow by a row and a column. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Label(d, b) CoordinatesRectangular ShellDiagonal Shell
A(0, 0)00
B(1, 0)11
C(1, 1)12
D(1, 2)23
E(2, 0)22
F(2, 1)23
G(2, 2)24
H(3, 0)33
I(3, 1)34
+ +

However such a grid cannot be directly printed to a stream. It is a simple matter to add a row by emitting a new line character, but adding a column would require editing downstream data.

+ +

A grid or ASCII-art view of the tree can be generated from a + line per shell output stream, though a new diagram will be required + for each new line found on the stream.

+ +

Here is a streamable rectangular shell per line output for the + tree.

+

+  Shell 0: A
+  Shell 1: B(A) C(A)
+  Shell 2: D(A) E(B) F(B) G(C)
+  Shell 3: H(G) I(G)
+  
+ +

And here it is as a diagonal shell per line.

+

+  Shell 0: A
+  Shell 1: B(A) 
+  Shell 2: C(A) E(B) 
+  Shell 3: D(A) F(B) H(G)
+  Shell 4: G(C) I(G)
+  
+ +

Note in this latter example, node H on shell 3 refers to parent G, but + G is not output until the next line. This is an example of a forward referencing problem while using diagonal shells.

+ + + + +

Algorithm 3: Unbounded Graph Iteration Without Forward Referencing

+

+This algorithm avoids forward referencing by ensuring that nodes are processed along with their child lists in a structured manner. It uses two lists to manage nodes: +

+
    +
  • list_of__unopened_node: Nodes that have not yet been processed to discover their child lists.
  • +
  • list_of__opened_incomplete_child_list: Partially processed child lists of nodes.
  • +
+ +

Initial Setup

+

+1. Print the root node. +2. If the root node has children, add its child list to list_of__unopened_node. +

+ +

Iteration Steps

+

At each step:

+
    +
  • + For each node in list_of__unopened_node: +
      +
    • Open the node to retrieve its child list.
    • +
    • If the child list is not null, add it to list_of__opened_incomplete_child_list.
    • +
    +
  • +
  • + For each child list in list_of__opened_incomplete_child_list: +
      +
    • Yield a node from the list (one at a time).
    • +
    • If the list becomes empty, remove it from list_of__opened_incomplete_child_list.
    • +
    • Print the node.
    • +
    • If the node has its own child list, add it to list_of__unopened_node.
    • +
    +
  • +
+ +

End Condition

+

+The process ends when both list_of__unopened_node and list_of__opened_incomplete_child_list are empty, ensuring all nodes are processed without forward referencing issues. +

+ + + +
+ + diff --git a/developer/example/CountingNumber.class b/developer/example/CountingNumber.class new file mode 100644 index 0000000..a4fa5c6 Binary files /dev/null and b/developer/example/CountingNumber.class differ diff --git a/developer/example/CountingNumber.java b/developer/example/CountingNumber.java new file mode 100644 index 0000000..579049e --- /dev/null +++ b/developer/example/CountingNumber.java @@ -0,0 +1,45 @@ +import com.ReasoningTechnology.Ariadne.Ariadne_SRM; +import com.ReasoningTechnology.Ariadne.Ariadne_Test; +import java.math.BigInteger; + +public class CountingNumber extends Ariadne_SRM{ + + private static final Ariadne_Test test = Ariadne_Test.make("Ariadne_SRM::"); + + public static CountingNumber make(){ + return new CountingNumber(); + } + + private BigInteger i; + + protected CountingNumber(){ + super(); + i = BigInteger.ZERO; + test.print("CountingNumber read() value initialized to: " + i); + } + + @Override + public Topology topology(){ + return Topology.INFINITE_RIGHT; // leftmost, no rightmost + } + + @Override + public Status status(){ + if( i.equals(BigInteger.ZERO) ) return Status.AT_LEFTMOST; + else return Status.AT_MIDWAY; + } + + @Override + public BigInteger read(){ + return i; // note that BigInteger is immutable + } + + @Override + public boolean step(){ + i = i.add(BigInteger.ONE); + test.print(" after step right new read() value: " + i); + return true; + } + +} + diff --git a/developer/example/Example_Ariadne_SRM b/developer/example/Example_Ariadne_SRM new file mode 100755 index 0000000..dadbafc --- /dev/null +++ b/developer/example/Example_Ariadne_SRM @@ -0,0 +1,2 @@ +#!/bin/bash +java Example_Ariadne_SRM diff --git a/developer/example/Example_Ariadne_SRM.class b/developer/example/Example_Ariadne_SRM.class new file mode 100644 index 0000000..ed6f5d6 Binary files /dev/null and b/developer/example/Example_Ariadne_SRM.class differ diff --git a/developer/example/Example_Ariadne_SRM.java b/developer/example/Example_Ariadne_SRM.java new file mode 100644 index 0000000..e7a4e28 --- /dev/null +++ b/developer/example/Example_Ariadne_SRM.java @@ -0,0 +1,20 @@ +import java.math.BigInteger; + +public class Example_Ariadne_SRM { + + public static void main(String[] args) { + CountingNumber counting_number = CountingNumber.make(); + + System.out.println("Initial Status: " + counting_number.status()); + System.out.println("Initial Read Value: " + counting_number.read()); + + for( int step_index = 0 ;step_index < 10 ;step_index++ ){ + counting_number.step(); + System.out.println( + "Step: " + step_index + +", Status: " + counting_number.status() + +", Read Value: " + counting_number.read() + ); + } + } +} diff --git "a/developer/javac\360\237\226\211/#Ariadne_Node.xjava#" "b/developer/javac\360\237\226\211/#Ariadne_Node.xjava#" new file mode 100644 index 0000000..d2d55b4 --- /dev/null +++ "b/developer/javac\360\237\226\211/#Ariadne_Node.xjava#" @@ -0,0 +1,50 @@ +package com.ReasoningTechnology.Ariadne; +import java.util.HashMap; +import java.util.HashSet; + +public class Ariadne_Node extends HashMap{ + + // owned by the class + // + public static Ariadne_Node make(Ariadne_Label label){ + return new Ariadne_Node(label); + } + + // data owned by the instance + // + private Ariadne_Label label; + private HashSet mark_set; + + // constructors + // + public Ariadne_Node(Ariadne_Label label){ + super(); + this.label = label; + this.market_set = new HashSet; + } + + // instance interface + // + public Ariadne_Label label(){ + return this.label; + } + + public Ariadne_StepRightMachine neighbor_set(); + + public void mark(Ariadne_Token token){ + mark_set.add(token); + } + + public boolean has_mark(Ariadne_Token token){ + return mark_set.contains(token); + } + + public Ariadne_LabelList neighbor(){ + return(Ariadne_LabelList) this.get(neighbor_property_name); + } + + // Object interface + // + + +} diff --git "a/developer/javac\360\237\226\211/Ariadne_DirectedGraph.xjava" "b/developer/javac\360\237\226\211/Ariadne_DirectedGraph.xjava" new file mode 100644 index 0000000..941d935 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_DirectedGraph.xjava" @@ -0,0 +1,26 @@ +package com.ReasoningTechnology.Ariadne; + +/* + To define a graph, extend this class and define `lookup`. + + For a wellformed graph, each start label will be a label for a node found in the graph. +*/ + + +import java.util.HashMap; +import java.util.Map; + +package com.ReasoningTechnology.Ariadne; + +public class Ariadne_Graph{ + + public static Ariadne_DirectedGraph make(Object...obj_list){ + return new Ariadne_DirectedGraph(); + } + + public Ariadne_StepRightMachine start(); + public Ariadne_StepRightMachine traverse(); + public Ariadne_Node lookup(String label); + + +} diff --git "a/developer/javac\360\237\226\211/Ariadne_File.java" "b/developer/javac\360\237\226\211/Ariadne_File.java" deleted file mode 100644 index 825b499..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_File.java" +++ /dev/null @@ -1,76 +0,0 @@ -package com.ReasoningTechnology.Ariadne; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class Ariadne_File { - static boolean debug = false; - - public static Map unpack_file_path(String file_fp) { - if (debug) System.out.println("unpack_file_path::file_fp: " + file_fp); - - // Use java.io.File explicitly to avoid conflict with the custom Ariadne_File class - java.io.File file = new java.io.File(file_fp); - String parent_dp = (file.getParent() != null) ? file.getParent() : ""; - - if (!parent_dp.isEmpty() && !parent_dp.endsWith(java.io.File.separator)) { - parent_dp += java.io.File.separator; - } - - String file_fn = file.getName(); - String file_fn_base = file_fn; - String file_fn_ext = ""; - - int last_index = file_fn.lastIndexOf('.'); - if (last_index > 0) { - file_fn_base = file_fn.substring(0, last_index); - if (last_index + 1 < file_fn.length()) { - file_fn_ext = file_fn.substring(last_index + 1); - } - } - - Map ret_val = new HashMap<>(); - ret_val.put("dp", parent_dp); - ret_val.put("fn", file_fn); - ret_val.put("fn_base", file_fn_base); - ret_val.put("fn_ext", file_fn_ext); - - if (debug) System.out.println("unpack_file_path::ret_val: " + ret_val); - - return ret_val; - } - - public static boolean file_exists_q(String fp_string) { - Path fp_object = Paths.get(fp_string); - return Files.exists(fp_object); - } - - /* - Given a target_fp and a list of dependency_fp. - - Returns false if the target is newer than all dependencies or if a file is missing; - otherwise, returns true. - */ - public static boolean newer_than_all(String target_fp_string, List dependency_fp_list) throws IOException { - Path target_fp_object = Paths.get(target_fp_string); - if (!Files.exists(target_fp_object)) return false; - - long target_last_modified_time = Files.getLastModifiedTime(target_fp_object).toMillis(); - - return dependency_fp_list.stream().allMatch(dependency_fp -> { - try { - Path dependency_fp_object = Paths.get(dependency_fp); - if (!Files.exists(dependency_fp_object)) return false; - long dependency_last_modified_time = Files.getLastModifiedTime(dependency_fp_object).toMillis(); - return target_last_modified_time > dependency_last_modified_time; - } catch (IOException e) { - return false; - } - }); - } -} diff --git "a/developer/javac\360\237\226\211/Ariadne_Graph.java" "b/developer/javac\360\237\226\211/Ariadne_Graph.java" index 6b54394..c91114d 100644 --- "a/developer/javac\360\237\226\211/Ariadne_Graph.java" +++ "b/developer/javac\360\237\226\211/Ariadne_Graph.java" @@ -1,73 +1,18 @@ package com.ReasoningTechnology.Ariadne; -import java.util.HashMap; -import java.util.Map; +/* + To define a graph, extend this class and define `start` and `lookup`. -public class Ariadne_Graph{ + For a wellformed graph, each start label will be a label for a node found in the graph. +*/ - // Test messaging - // - private static boolean test = false; - public static void test_switch(boolean test){ - if (Ariadne_Graph.test && !test){ - test_print("Ariadne_Graph:: test messages off"); - } - if (!Ariadne_Graph.test && test){ - test_print("Ariadne_Graph:: test messages on"); - } - } - private static void test_print(String message){ - if(test){ - System.out.println(message); - } - } +public interface Ariadne_Graph{ - // Class data (static data) - // + public static Ariadne_Graph make(Object...obj_list){ + return new Ariadne_Graph(); + } - - // Instance data and access - // - private Map node_map; - private Ariadne_ProductionList recognizer_f_list; - - // Constructors - // - public Ariadne_Graph(Map node_map, Ariadne_ProductionList recognizer_f_list){ - if (node_map == null && recognizer_f_list == null){ - System.err.println("Ariadne_Graph: At least one of 'node_map' (Map) or 'recognizer_f_list' (List) must be provided."); - System.exit(1); - } - - // Initialize each of node_map and recognizer_f_list to empty collections if null - this.node_map = (node_map != null) ? node_map : new HashMap<>(); - this.recognizer_f_list = (recognizer_f_list != null) ? recognizer_f_list : new Ariadne_ProductionList(); - } - - // Interface methods - // - - // Lookup by label - public Ariadne_Node lookup(Ariadne_Label node_label){ - if (node_label == null || node_label.isEmpty()){ - if (verbose){ - System.out.println("lookup:: given node_label is null or empty."); - } - return null; - } - - // Try to retrieve the node from the map - Ariadne_Node node = this.node_map.get(node_label); - - if(test) - if(node == null) test_print("lookup:: node not found for label: " + node_label); - else test_print("lookup:: found node: " + node); - - return node; - } - - // standard interface - // - // need a toString ... + public Ariadne_SRM start(); + public Ariadne_Node lookup(String label); } diff --git "a/developer/javac\360\237\226\211/Ariadne_GraphDirectedAcyclic.java" "b/developer/javac\360\237\226\211/Ariadne_GraphDirectedAcyclic.java" deleted file mode 100644 index 948dc47..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_GraphDirectedAcyclic.java" +++ /dev/null @@ -1,218 +0,0 @@ -package com.ReasoningTechnology.Ariadne; - -import java.util.HashMap; -import java.util.Map; -import java.util.List; -import java.util.ArrayList; - -public class Ariadne_GraphDirectedAcyclic extends Ariadne_Graph { - - /*-------------------------------------------------------------------------------- - Constructors - */ - - public Ariadne_GraphDirectedAcyclic() { - super(new HashMap<>(), null); - } - - public Ariadne_GraphDirectedAcyclic(Map node_map, Ariadne_ProductionList recognizer_f_list, Ariadne_LabelList root_node_list, int max_depth, boolean verbose) { - super(node_map, recognizer_f_list); - Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list, max_depth, verbose); - } - - public Ariadne_GraphDirectedAcyclic(Map node_map, Ariadne_ProductionList recognizer_f_list, Ariadne_LabelList root_node_list) { - super(node_map, recognizer_f_list); - Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list); - } - - /*-------------------------------------------------------------------------------- - Instance Data Extension - */ - - private static boolean debug = true; - - /*-------------------------------------------------------------------------------- - Interface - */ - - private List path_find_cycle(Ariadne_LabelList path) { - if (path.size() <= 1) return null; - - int rightmost_index = path.size() - 1; - Ariadne_Label rightmost_node_label = path.get(rightmost_index); - - int cycle_leftmost_index = path.indexOf(rightmost_node_label); - Boolean has_cycle = cycle_leftmost_index < rightmost_index; - if (!has_cycle) return null; - - List result = new ArrayList<>(); - result.add(cycle_leftmost_index); - result.add(rightmost_index); - return result; - } - - private boolean graph_descend_cycle_case(Ariadne_LabelList left_path, List path_stack, boolean verbose) { - - List cycle_index_interval = path_find_cycle(left_path); - if (cycle_index_interval == null) { - return false; - } - - int cycle_i0 = cycle_index_interval.get(0); - int cycle_n = cycle_index_interval.get(1); - - if (verbose) Ariadne_Util.print_list( - "Found cycle:", - left_path.subList(cycle_i0, cycle_n + 1) - ); - - Ariadne_LabelList undefined_node_list = new Ariadne_LabelList(); - for (int i = cycle_i0; i <= cycle_n; i++) { - Ariadne_Label node_label = left_path.get(i); - Ariadne_Node node = super.lookup(node_label); - if (node != null) { - node.mark(new Ariadne_Token("cycle_member")); - } else { - undefined_node_list.add(node_label); - } - } - - if (verbose) Ariadne_Util.print_list( - "Each undefined node could not be marked as a cycle member:", - undefined_node_list - ); - - path_stack.subList(cycle_i0 + 1, cycle_n + 1).clear(); - - return true; - } - - private static Ariadne_TokenSet graph_descend_set = new Ariadne_TokenSet() {{ - add(new Ariadne_Token("empty_path_stack")); - add(new Ariadne_Token("cycle_found")); - add(new Ariadne_Token("undefined_node")); - add(new Ariadne_Token("leaf")); - add(new Ariadne_Token("max_depth_reached")); - }}; - - private Ariadne_TokenSet graph_descend(List path_stack, int max_depth, boolean verbose) { - Ariadne_TokenSet ret_value = new Ariadne_TokenSet(); - - if (path_stack.isEmpty()) { - ret_value.add(new Ariadne_Token("empty_path_stack")); - return ret_value; - } - - Ariadne_LabelList left_path = new Ariadne_LabelList(); - for (Ariadne_LabelList neighbor_list : path_stack) { - left_path.add(neighbor_list.get(0)); - } - - do { - - if (graph_descend_cycle_case(left_path, path_stack, verbose)) { - ret_value.add(new Ariadne_Token("cycle_found")); - return ret_value; - } - - Ariadne_Label it_node_label = path_stack.get(path_stack.size() - 1).get(0); - Ariadne_Node it_node = super.lookup(it_node_label); - if (it_node == null) { - ret_value.add(new Ariadne_Token("undefined_node")); - return ret_value; - } - - Ariadne_LabelList neighbor_list = it_node.neighbor_LabelList(); - if (neighbor_list.isEmpty()) { - ret_value.add(new Ariadne_Token("leaf")); - return ret_value; - } - - path_stack.add(new Ariadne_LabelList(neighbor_list)); - Ariadne_Label it_next_label = neighbor_list.get(0); - left_path.add(it_next_label); - - if (max_depth > 0) { - max_depth--; - if (max_depth == 0) { - if (verbose) { - Ariadne_Util.print_list("GraphDirectedAcyclic.GraphDescend:: max_depth reached, ending descent:", path_stack); - } - ret_value.add(new Ariadne_Token("max_depth_reached")); - return ret_value; - } - } - - } while (true); - } - - public static Ariadne_TokenSet graph_mark_cycles_set = new Ariadne_TokenSet() {{ - add(new Ariadne_Token("empty_root_label_list")); - add(new Ariadne_Token("cycle_exists")); - add(new Ariadne_Token("undefined_node_exists")); - add(new Ariadne_Token("bad_descent_termination")); - add(new Ariadne_Token("max_depth_reached")); - }}; - - public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList, int max_depth, boolean verbose) { - Ariadne_TokenSet ret_value = new Ariadne_TokenSet(); - boolean exists_malformed = false; - Ariadne_TokenSet result; - - if (root_node_LabelList.isEmpty()) { - ret_value.add(new Ariadne_Token("empty_root_label_list")); - return ret_value; - } - - List path_stack = new ArrayList<>(); - path_stack.add(new Ariadne_LabelList(root_node_LabelList)); - - do { - result = graph_descend(path_stack, max_depth, verbose); - if (result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("cycle_exists")); - if (result.contains(new Ariadne_Token("undefined_node"))) ret_value.add(new Ariadne_Token("undefined_node_exists")); - if (result.contains(new Ariadne_Token("max_depth_reached"))) ret_value.add(new Ariadne_Token("max_depth_reached")); - if (!result.contains(new Ariadne_Token("leaf")) && !result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("bad_descent_termination")); - - Ariadne_LabelList top_list = path_stack.get(path_stack.size() - 1); - top_list.remove(0); - if (top_list.isEmpty()) path_stack.remove(path_stack.size() - 1); - - } while (!path_stack.isEmpty()); - - if (verbose) { - if (ret_value.contains("bad_descent_termination")) { - System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: terminated with unexpected condition."); - } - if (ret_value.contains("cycle_exists")) { - System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: One or more cycles detected."); - } - if (ret_value.contains("undefined_node_exists")) { - System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: Undefined nodes exist."); - } - } - - return ret_value; - } - - public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList) { - return graph_mark_cycles(root_node_LabelList, this.debug ? 40 : -1, this.debug); - } - - @Override - public Ariadne_Node lookup(Ariadne_Label node_label, boolean verbose) { - Ariadne_Node node = super.lookup(node_label, verbose); - if (node != null && node.has_mark(new Ariadne_Token("cycle_member"))) { - if (verbose) { - System.out.println("GraphDirectedAcyclic.lookup:: Node is part of a cycle, not returned: " + node_label); - } - return null; - } - return node; - } - - public Ariadne_Node lookup(Ariadne_Label node_label) { - return lookup(node_label, this.debug); - } - -} diff --git "a/developer/javac\360\237\226\211/Ariadne_Label.java" "b/developer/javac\360\237\226\211/Ariadne_Label.java" index 9f10fcb..c97f0a3 100644 --- "a/developer/javac\360\237\226\211/Ariadne_Label.java" +++ "b/developer/javac\360\237\226\211/Ariadne_Label.java" @@ -1,5 +1,7 @@ package com.ReasoningTechnology.Ariadne; + + /* A value for the node.label property. @@ -8,18 +10,27 @@ package com.ReasoningTechnology.Ariadne; */ public class Ariadne_Label{ - private final String value; - public Ariadne_Label(String value){ - this.value = value; + // owned by class + + + // data owned by instance + + private final String value; + + // constructors + + + private Ariadne_Label(String s){ + this.value = s; } - public boolean isEmpty(){ - return value.isEmpty(); + Ariadne_Label make(String s){ + return new Ariadne_Label(s); } - public String get(){ - return value; + public boolean isEmpty(){ + return value.isEmpty(); } @Override @@ -39,4 +50,5 @@ public class Ariadne_Label{ public int hashCode(){ return value.hashCode(); } + } diff --git "a/developer/javac\360\237\226\211/Ariadne_LabelList.java" "b/developer/javac\360\237\226\211/Ariadne_LabelList.java" deleted file mode 100644 index ae2dd0b..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_LabelList.java" +++ /dev/null @@ -1,18 +0,0 @@ -// LabelList.java -package com.ReasoningTechnology.Ariadne; -import java.util.List; -import java.util.ArrayList; - -public class Ariadne_LabelList extends ArrayList{ - // Constructor - public Ariadne_LabelList(){ - super(); - } - public Ariadne_LabelList(List labels){ - super(); // Initialize the parent class - if(labels != null){ - this.addAll(labels); // Copy all elements from the provided list - } - } - -} diff --git "a/developer/javac\360\237\226\211/Ariadne_LabelList.xjava" "b/developer/javac\360\237\226\211/Ariadne_LabelList.xjava" new file mode 100644 index 0000000..6b2c3e0 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_LabelList.xjava" @@ -0,0 +1,67 @@ +/* +A list of Labels. +*/ + +package com.ReasoningTechnology.Ariadne; + +import java.util.List; +import java.util.ArrayList; + +public class Ariadne_LabelList extends ArrayList{ + + // owned by the class + // + public static Ariadne_LabelList make(Object...label_list){ + return new Ariadne_LabelList(label_list); + } + + // data owned by the instance + // + + // constructors + // + public Ariadne_LabelList(Object...label_list){ + super(); + if(label_list != null){ + this.add(List.of(label_list)); // Delegate work to the add method + } + } + + // instance interface + // + public boolean add(Object...obj_list){ + boolean modified = false; + if(obj_list != null) for(Object obj:obj_list) modified |= add_one(obj); + return modified; + } + + // Object interface + // + @Override + public String toString(){ + return super.toString(); + } + + // private helpers + // + private boolean add_one(Object obj){ + if(obj instanceof String){ + return add_one((String) obj); + }else if(obj instanceof Ariadne_Label){ + return add_one((Ariadne_Label) obj); + } + throw new IllegalArgumentException( + "Ariadne_LabelList::add_one, cannot make label from object of type: " + obj.getClass().getName() + ); + } + + private boolean add_one(String string){ + return super.add(Ariadne_Label.make(string)); + } + + private boolean add_one(Ariadne_Label label){ + return super.add(label); + } +} + + diff --git "a/developer/javac\360\237\226\211/Ariadne_Node.java" "b/developer/javac\360\237\226\211/Ariadne_Node.java" index 0c49ac2..fac11d5 100644 --- "a/developer/javac\360\237\226\211/Ariadne_Node.java" +++ "b/developer/javac\360\237\226\211/Ariadne_Node.java" @@ -1,30 +1,50 @@ package com.ReasoningTechnology.Ariadne; import java.util.HashMap; +import java.util.HashSet; public class Ariadne_Node extends HashMap{ - private static String mark_property_name = "mark"; - private static String neighbor_property_name = "neighbor"; + // owned by the class + // + public static Ariadne_Node make(Ariadne_Label label){ + return new Ariadne_Node(label); + } + + // data owned by the instance + // + private Ariadne_Label label; + private HashSet mark_set; - public Ariadne_Node(){ + // constructors + // + public Ariadne_Node(Ariadne_Label label){ super(); - this.put(neighbor_property_name, new Ariadne_LabelList()); + this.label = label; + this.market_set = new HashSet; + } + + // instance interface + // + public Ariadne_Label label(){ + return this.label; } + public Ariadne_StepRightMachine neighbor_set(); + public void mark(Ariadne_Token token){ - if(this.get(mark_property_name) == null){ - this.put(mark_property_name, new Ariadne_TokenSet()); - } - ((Ariadne_TokenSet) this.get(mark_property_name)).add(token); + mark_set.add(token); } public boolean has_mark(Ariadne_Token token){ - Ariadne_TokenSet mark =(Ariadne_TokenSet) this.get(mark_property_name); - return mark != null && mark.contains(token); + return mark_set.contains(token); } - public Ariadne_LabelList neighbor_LabelList(){ + public Ariadne_LabelList neighbor(){ return(Ariadne_LabelList) this.get(neighbor_property_name); } + // Object interface + // + + } diff --git "a/developer/javac\360\237\226\211/Ariadne_NodeList.java" "b/developer/javac\360\237\226\211/Ariadne_NodeList.java" deleted file mode 100644 index 69e4284..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_NodeList.java" +++ /dev/null @@ -1,10 +0,0 @@ -// NodeList.java -package com.ReasoningTechnology.Ariadne; -import java.util.ArrayList; - -public class Ariadne_NodeList extends ArrayList { - // Constructor - public Ariadne_NodeList(){ - super(); - } -} diff --git "a/developer/javac\360\237\226\211/Ariadne_NodeList.xjava" "b/developer/javac\360\237\226\211/Ariadne_NodeList.xjava" new file mode 100644 index 0000000..69e4284 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_NodeList.xjava" @@ -0,0 +1,10 @@ +// NodeList.java +package com.ReasoningTechnology.Ariadne; +import java.util.ArrayList; + +public class Ariadne_NodeList extends ArrayList { + // Constructor + public Ariadne_NodeList(){ + super(); + } +} diff --git "a/developer/javac\360\237\226\211/Ariadne_Production.java" "b/developer/javac\360\237\226\211/Ariadne_Production.java" deleted file mode 100644 index ab6aed9..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_Production.java" +++ /dev/null @@ -1,5 +0,0 @@ -// Production.java -package com.ReasoningTechnology.Ariadne; -import java.util.function.Function; - -public interface Ariadne_Production extends Function {} diff --git "a/developer/javac\360\237\226\211/Ariadne_ProductionList.java" "b/developer/javac\360\237\226\211/Ariadne_ProductionList.java" deleted file mode 100644 index 03b2461..0000000 --- "a/developer/javac\360\237\226\211/Ariadne_ProductionList.java" +++ /dev/null @@ -1,10 +0,0 @@ -// ProductionList.java -package com.ReasoningTechnology.Ariadne; -import java.util.ArrayList; - -public class Ariadne_ProductionList extends ArrayList { - // Constructor - public Ariadne_ProductionList(){ - super(); - } -} diff --git "a/developer/javac\360\237\226\211/Ariadne_SRM.java" "b/developer/javac\360\237\226\211/Ariadne_SRM.java" new file mode 100644 index 0000000..a2aee82 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_SRM.java" @@ -0,0 +1,73 @@ +/* + A 'tape' as a model for computation is a sequence of cells, where something can be written or read from each cell. We talk about the sequence as though written on paper, running from left to right. The elements in the sequence have neighbors, so the sequence of cells can be said to be mutually connected. This is to say that if cell B is to the right of cell A in the sequence, then cell A is to the left of cell B; Also if cell A is to the left of cell B, then cell B is to the right of cell A. + + One of the cells on the tape is specially marked as being the 'mounted cell'. This is the cell that can be written or read after the tape is mounted on a 'tape machine', and before any steps have been taken. + + Information from the `topology` method will remain valid for as long as the topology of + the tape is not modified. + + A finite tape will have a leftmost cell, which has no left neighbor, and a rightmost cell, which has no right neighbor. All other cells will have two neighbors. + + A tape can have an infinite number of cells to the left of the mount point, to the right of the mount point, or in both directions. Hence it is possible that two, one, or zero cells on a tape have only one neighbor, where the zero neighbor case is for finite tapes, and the latter cases are for infinite tapes. + + An algorithm running on a tape machine that has a left going tape can be translated into an algorithm for a right going tape simply by swapping `step_right` for `step_left`. Hence there is no utility to be had by keeping both models. + + Another isomorphism can be setup between a single ended tape and a double direction tape by replacing each step by two steps, and then placing odd cell into correspondence with the right going tape, and even cells with left going tape. Hence an algorithm implemented over the top of either can be mechanically transformed to an algorithm for the other. + + However, what we can not do without affecting the power of our computation machine is to + eliminate 'step-left', yet this is a common simplification in data structures. The Lisp language is based on single linked lists for example. + + This 'Step Right Machine' (SRM) defined here can only be stepped to the right. Thus whether cells are mutually connected, or not, becomes irrelevant. Also, saying 'leftmost' is a feature of the tape, becomes muddled, as the mount point cell will be the leftmost cell that is ever visited. + + A SRM can be defined using functions, or it can be used as an iterator for traversing through a container. + + The property methods defined here are kept general so that they can be used with other tape machines. +*/ + +package com.ReasoningTechnology.Ariadne; + +public class Ariadne_SRM{ + + // Enum for Tape Topology + public enum Topology{ + NO_CELLS + ,SEGMENT + ,CIRCLE + ,INFINITE_RIGHT + ,INFINITE_LEFT + ,INFINITE + ,UNKNOWN + ,UNDEFINED + ; + } + + // Enum for Machine Status + public enum Status{ + TAPE_NOT_MOUNTED + ,AT_LEFTMOST + ,AT_MIDWAY + ,AT_RIGHTMOST + ; + } + + public static Ariadne_SRM make(){ + return new Ariadne_SRM<>(); + } + protected Ariadne_SRM(){} + + public Topology topology(){ + return Topology.UNDEFINED; // Default topology + } + + public Status status(){ + return Status.TAPE_NOT_MOUNTED; // Default status + } + + public T read(){ + throw new UnsupportedOperationException("Ariadne_SRM::can't read unmounted tape."); + } + + public boolean step(){ + throw new UnsupportedOperationException("Ariadne_SRM::can't step unmounted tape."); + } +} diff --git "a/developer/javac\360\237\226\211/Ariadne_SRMI.java" "b/developer/javac\360\237\226\211/Ariadne_SRMI.java" new file mode 100644 index 0000000..60ec791 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_SRMI.java" @@ -0,0 +1,35 @@ +/* +Ariadne_SRM with index + +*/ + +package com.ReasoningTechnology.Ariadne; +import java.math.BigInteger; + +public class Ariadne_SRMI extends Ariadne_SRM{ + + private BigInteger index; + + public static Ariadne_SRMI make(){ + return new Ariadne_SRMI(); + } + protected Ariadne_SRMI(){ + super(); + index = BigInteger.ZERO;; + } + + @Override + public boolean step(){ + throw new UnsupportedOperationException("Ariadne_SRMI::can't step unmounted tape."); + // index.add(BigInteger.ONE); + } + + BigInteger index(){return index;} + BigInteger leftmost_index(){ + return BigInteger.ZERO; + } + BigInteger rightmost_index(){ + throw new UnsupportedOperationException("Ariadne_SRMI:: rightmost_index() of undefined."); + } + +} diff --git "a/developer/javac\360\237\226\211/Ariadne_Test.java" "b/developer/javac\360\237\226\211/Ariadne_Test.java" new file mode 100644 index 0000000..5ce6637 --- /dev/null +++ "b/developer/javac\360\237\226\211/Ariadne_Test.java" @@ -0,0 +1,32 @@ +package com.ReasoningTechnology.Ariadne; + +public class Ariadne_Test { + + private boolean test = false; + private String prefix = ""; + + public static Ariadne_Test make(String prefix){ + Ariadne_Test instance = new Ariadne_Test(); + instance.prefix = prefix; + return instance; + } + + protected Ariadne_Test(){ + } + + public void switch_test(boolean enable){ + if( test && !enable ){ + print("test messages off"); + } + if( !test && enable ){ + print("test messages on"); + } + test = enable; + } + + public void print(String message){ + if( test ){ + System.out.println(prefix + message); + } + } +} diff --git "a/developer/javac\360\237\226\211/Build.javax" "b/developer/javac\360\237\226\211/Build.javax" deleted file mode 100644 index b0cdab3..0000000 --- "a/developer/javac\360\237\226\211/Build.javax" +++ /dev/null @@ -1,76 +0,0 @@ -import java.util.List; - -public class Build { - - // Function to load the graph class dynamically - public static Class includeAClass(String aClassFp) { - ClassLoader classLoader = Build.class.getClassLoader(); - String className = aClassFp.replace('/', '.').replace(".class", ""); - try { - return classLoader.loadClass(className); - } catch (Exception e) { - System.out.println("Error loading class '" + className + "': " + e.getMessage()); - return null; - } - } - - // Build function - public static void build(String graphDefinitionFp, List rootNodeLabels) { - // Print summary of what we are doing - System.out.println("build:: Building targets for graph '" + graphDefinitionFp + ".class'"); - if (rootNodeLabels.isEmpty()) { - System.out.println("No build targets specified. Please provide root node labels to build."); - System.exit(0); - } - System.out.println("Building targets: " + String.join(", ", rootNodeLabels)); - - // Load the dependency graph class from arg[1] - Class graphDefinitionClass = includeAClass(graphDefinitionFp); - if (graphDefinitionClass != null) { - System.out.println("build:: loaded " + graphDefinitionFp + ".class"); - } else { - System.out.println("build:: failed to load " + graphDefinitionFp + ".class"); - System.exit(1); - } - - // Get the node_map and node_f_list from the graph class - // Assuming these methods are static and return the appropriate types - // Replace with actual method calls if they are different - Object nodeMap = null; - Object nodeFList = null; - try { - nodeMap = graphDefinitionClass.getMethod("getNodeMap").invoke(null); - nodeFList = graphDefinitionClass.getMethod("getNodeFList").invoke(null); - } catch (Exception e) { - System.out.println("Error invoking methods on graphDefinitionClass: " + e.getMessage()); - System.exit(1); - } - System.out.println("node_map: " + nodeMap); - System.out.println("node_f_list: " + nodeFList); - - // Create an instance of AriadneGraph, and run the build scripts - // Assuming AriadneGraph has a constructor that takes nodeMap and nodeFList - // Replace with actual constructor call if it is different - try { - Class ariadneGraphClass = Class.forName("AriadneGraph"); - Object graph = ariadneGraphClass.getConstructor(nodeMap.getClass(), nodeFList.getClass()).newInstance(nodeMap, nodeFList); - ariadneGraphClass.getMethod("runBuildScriptsF", List.class).invoke(graph, rootNodeLabels); - } catch (Exception e) { - System.out.println("Error creating or invoking AriadneGraph: " + e.getMessage()); - System.exit(1); - } - } - - // Entry point when run as a script - public static void main(String[] args) { - if (args.length == 0) { - System.out.println("Usage: ./build [root_node_labels...]"); - System.exit(1); - } - - // Get graph definition file and root node labels - String graphDefinitionFp = args[0]; - List rootNodeLabels = args.length > 1 ? List.of(args).subList(1, args.length) : List.of(); - build(graphDefinitionFp, rootNodeLabels); - } -} diff --git "a/developer/javac\360\237\226\211/DirectedGraph.xjava" "b/developer/javac\360\237\226\211/DirectedGraph.xjava" new file mode 100644 index 0000000..c8b2420 --- /dev/null +++ "b/developer/javac\360\237\226\211/DirectedGraph.xjava" @@ -0,0 +1,234 @@ +package com.ReasoningTechnology.Ariadne; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +public class Ariadne_GraphDirectedAcyclic extends Ariadne_Graph{ + + // test messaging + // + private static boolean test = false; + public static void test_switch(boolean test){ + if(Ariadne_Graph.test && !test){ + test_print("Ariadne_Graph:: test messages off"); + } + if(!Ariadne_Graph.test && test){ + test_print("Ariadne_Graph:: test messages on"); + } + } + private static void test_print(String message){ + if(test){ + System.out.println(message); + } + } + + // class data + // + + // marks this class might put on a node + public static Ariadne_TokenSet node_marks = new Ariadne_TokenSet(){{ + add(new Ariadne_Token("empty_root_label_list")); + add(new Ariadne_Token("cycle_exists")); + add(new Ariadne_Token("undefined_node_exists")); + add(new Ariadne_Token("bad_descent_termination")); + add(new Ariadne_Token("max_depth_reached")); + }}; + + // graph descend method return values + private static Ariadne_TokenSet graph_descend_set = new Ariadne_TokenSet(){{ + add(new Ariadne_Token("empty_path_stack")); + add(new Ariadne_Token("cycle_found")); + add(new Ariadne_Token("undefined_node")); + add(new Ariadne_Token("leaf")); + add(new Ariadne_Token("max_depth_reached")); + }}; + + + // instance data + + // constructors + // + public Ariadne_GraphDirectedAcyclic(){ + super(new HashMap<>(), null); + } + + public Ariadne_GraphDirectedAcyclic(Map node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list, int max_depth, boolean verbose){ + super(node_map, recognizer_f_list); + Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list, max_depth, verbose); + } + + public Ariadne_GraphDirectedAcyclic(Map node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list){ + super(node_map, recognizer_f_list); + Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list); + } + + // interface functions + // + private List path_find_cycle(Ariadne_LabelList path){ + if(path.size() <= 1) return null; + + int rightmost_index = path.size() - 1; + Ariadne_Label rightmost_node_label = path.get(rightmost_index); + + int cycle_leftmost_index = path.indexOf(rightmost_node_label); + Boolean has_cycle = cycle_leftmost_index < rightmost_index; + if(!has_cycle) return null; + + List result = new ArrayList<>(); + result.add(cycle_leftmost_index); + result.add(rightmost_index); + return result; + } + + private boolean graph_descend_cycle_case(Ariadne_LabelList left_path, List path_stack, boolean verbose){ + + List cycle_index_interval = path_find_cycle(left_path); + if(cycle_index_interval == null){ + return false; + } + + int cycle_i0 = cycle_index_interval.get(0); + int cycle_n = cycle_index_interval.get(1); + + if(verbose) Ariadne_Util.print_list( + "Found cycle:", + left_path.subList(cycle_i0, cycle_n + 1) + ); + + Ariadne_LabelList undefined_node_list = new Ariadne_LabelList(); + for (int i = cycle_i0; i <= cycle_n; i++){ + Ariadne_Label node_label = left_path.get(i); + Ariadne_Node node = super.lookup(node_label); + if(node != null){ + node.mark(new Ariadne_Token("cycle_member")); + } else{ + undefined_node_list.add(node_label); + } + } + + if(verbose) Ariadne_Util.print_list( + "Each undefined node could not be marked as a cycle member:", + undefined_node_list + ); + + path_stack.subList(cycle_i0 + 1, cycle_n + 1).clear(); + + return true; + } + + private Ariadne_TokenSet graph_descend(List path_stack, int max_depth, boolean verbose){ + Ariadne_TokenSet ret_value = new Ariadne_TokenSet(); + + if(path_stack.isEmpty()){ + ret_value.add(new Ariadne_Token("empty_path_stack")); + return ret_value; + } + + Ariadne_LabelList left_path = new Ariadne_LabelList(); + for (Ariadne_LabelList neighbor_list : path_stack){ + left_path.add(neighbor_list.get(0)); + } + + do{ + + if(graph_descend_cycle_case(left_path, path_stack, verbose)){ + ret_value.add(new Ariadne_Token("cycle_found")); + return ret_value; + } + + Ariadne_Label it_node_label = path_stack.get(path_stack.size() - 1).get(0); + Ariadne_Node it_node = super.lookup(it_node_label); + if(it_node == null){ + ret_value.add(new Ariadne_Token("undefined_node")); + return ret_value; + } + + Ariadne_LabelList neighbor_list = it_node.neighbor_LabelList(); + if(neighbor_list.isEmpty()){ + ret_value.add(new Ariadne_Token("leaf")); + return ret_value; + } + + path_stack.add(new Ariadne_LabelList(neighbor_list)); + Ariadne_Label it_next_label = neighbor_list.get(0); + left_path.add(it_next_label); + + if(max_depth > 0){ + max_depth--; + if(max_depth == 0){ + if(verbose){ + Ariadne_Util.print_list("GraphDirectedAcyclic.GraphDescend:: max_depth reached, ending descent:", path_stack); + } + ret_value.add(new Ariadne_Token("max_depth_reached")); + return ret_value; + } + } + + } while (true); + } + + + public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList, int max_depth, boolean verbose){ + Ariadne_TokenSet ret_value = new Ariadne_TokenSet(); + boolean exists_malformed = false; + Ariadne_TokenSet result; + + if(root_node_LabelList.isEmpty()){ + ret_value.add(new Ariadne_Token("empty_root_label_list")); + return ret_value; + } + + List path_stack = new ArrayList<>(); + path_stack.add(new Ariadne_LabelList(root_node_LabelList)); + + do{ + result = graph_descend(path_stack, max_depth, verbose); + if(result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("cycle_exists")); + if(result.contains(new Ariadne_Token("undefined_node"))) ret_value.add(new Ariadne_Token("undefined_node_exists")); + if(result.contains(new Ariadne_Token("max_depth_reached"))) ret_value.add(new Ariadne_Token("max_depth_reached")); + if(!result.contains(new Ariadne_Token("leaf")) && !result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("bad_descent_termination")); + + Ariadne_LabelList top_list = path_stack.get(path_stack.size() - 1); + top_list.remove(0); + if(top_list.isEmpty()) path_stack.remove(path_stack.size() - 1); + + } while (!path_stack.isEmpty()); + + if(verbose){ + if(ret_value.contains("bad_descent_termination")){ + System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: terminated with unexpected condition."); + } + if(ret_value.contains("cycle_exists")){ + System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: One or more cycles detected."); + } + if(ret_value.contains("undefined_node_exists")){ + System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: Undefined nodes exist."); + } + } + + return ret_value; + } + + public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList){ + return graph_mark_cycles(root_node_LabelList, this.debug ? 40 : -1, this.debug); + } + + @Override + public Ariadne_Node lookup(Ariadne_Label node_label, boolean verbose){ + Ariadne_Node node = super.lookup(node_label, verbose); + if(node != null && node.has_mark(new Ariadne_Token("cycle_member"))){ + if(verbose){ + System.out.println("GraphDirectedAcyclic.lookup:: Node is part of a cycle, not returned: " + node_label); + } + return null; + } + return node; + } + + public Ariadne_Node lookup(Ariadne_Label node_label){ + return lookup(node_label, this.debug); + } + +} diff --git "a/developer/javac\360\237\226\211/File.java" "b/developer/javac\360\237\226\211/File.java" new file mode 100644 index 0000000..d0b250c --- /dev/null +++ "b/developer/javac\360\237\226\211/File.java" @@ -0,0 +1,79 @@ +package com.ReasoningTechnology.Ariadne; +/* + Utilities for dealing with files. +*/ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class File { + static boolean debug = false; + + public static Map unpack_file_path(String file_fp) { + if (debug) System.out.println("unpack_file_path::file_fp: " + file_fp); + + // Use java.io.File explicitly to avoid conflict with the custom Ariadne_File class + java.io.File file = new java.io.File(file_fp); + String parent_dp = (file.getParent() != null) ? file.getParent() : ""; + + if (!parent_dp.isEmpty() && !parent_dp.endsWith(java.io.File.separator)) { + parent_dp += java.io.File.separator; + } + + String file_fn = file.getName(); + String file_fn_base = file_fn; + String file_fn_ext = ""; + + int last_index = file_fn.lastIndexOf('.'); + if (last_index > 0) { + file_fn_base = file_fn.substring(0, last_index); + if (last_index + 1 < file_fn.length()) { + file_fn_ext = file_fn.substring(last_index + 1); + } + } + + Map ret_val = new HashMap<>(); + ret_val.put("dp", parent_dp); + ret_val.put("fn", file_fn); + ret_val.put("fn_base", file_fn_base); + ret_val.put("fn_ext", file_fn_ext); + + if (debug) System.out.println("unpack_file_path::ret_val: " + ret_val); + + return ret_val; + } + + public static boolean file_exists_q(String fp_string) { + Path fp_object = Paths.get(fp_string); + return Files.exists(fp_object); + } + + /* + Given a target_fp and a list of dependency_fp. + + Returns false if the target is newer than all dependencies or if a file is missing; + otherwise, returns true. + */ + public static boolean newer_than_all(String target_fp_string, List dependency_fp_list) throws IOException { + Path target_fp_object = Paths.get(target_fp_string); + if (!Files.exists(target_fp_object)) return false; + + long target_last_modified_time = Files.getLastModifiedTime(target_fp_object).toMillis(); + + return dependency_fp_list.stream().allMatch(dependency_fp -> { + try { + Path dependency_fp_object = Paths.get(dependency_fp); + if (!Files.exists(dependency_fp_object)) return false; + long dependency_last_modified_time = Files.getLastModifiedTime(dependency_fp_object).toMillis(); + return target_last_modified_time > dependency_last_modified_time; + } catch (IOException e) { + return false; + } + }); + } +} diff --git "a/developer/javac\360\237\226\211/GraphAriadne.javax" "b/developer/javac\360\237\226\211/GraphAriadne.javax" deleted file mode 100644 index a5949fe..0000000 --- "a/developer/javac\360\237\226\211/GraphAriadne.javax" +++ /dev/null @@ -1,376 +0,0 @@ -package com.ReasoningTechnology.Ariadne; - -import java.util.HashMap; -import java.util.Map; - -public class AriadnaGraph extends Graph{ - - /*-------------------------------------------------------------------------------- - constructors - */ - - public Graph(Map