damn dope graph build based on A* search

master
Theunis J. Botha 2021-07-01 11:04:00 +02:00
parent 7234726501
commit f6adda0a7b
2 changed files with 337 additions and 0 deletions

265
graph.php Normal file
View File

@ -0,0 +1,265 @@
<?php
class Graph
{
protected $initialList;
protected $open;
protected $closed;
public $nodes;
/**
* @throws ErrorException
*/
public function __construct(
$__initialList
)
{
$this->initialList = $__initialList;
$this->open = [];
/**
* Step 2. Create a list called CLOSED initially empty
*/
$this->closed = [];
$this->nodes = [];
/**
* Step 1. Create a Search graph
*/
$this->build();
}
/**
* @return Node
* @throws Exception
*/
protected function popFirst(&$__list)
{
/**
* Step 3. If OPEN is empty - throw error (we are actually done)
*/
if (sizeof($__list) === 0) {
throw new Exception("Done");
}
return array_splice($__list, 0, 1)[0];
}
protected function remove($__name, &$__list)
{
for ($i = 0; $i < sizeof($__list); $i++) {
if ($__list[$i]->name === $__name) {
return array_splice($__list, $i, 1)[0];
}
}
throw new ErrorException('Node not found in list : ' . $__name);
}
protected function removeAll($__parent, &$__list)
{
$nodes = [];
for ($i = sizeof($__list) - 1; $i >= 0; $i--) {
if ($__list[$i]->parent === $__parent) {
array_push($nodes, array_splice($__list, $i, 1)[0]);
}
}
return $nodes;
}
protected function expand($node)
{
if ($node->name === 'R3') {
$children = $this->removeAll(null, $this->initialList);
} else {
$children = $this->removeAll($node->name, $this->initialList);
}
return $children;
}
protected function linkToParent($node)
{
foreach ($node->children as $child) {
$child->parent = $node;
}
}
protected function pushToList(&$__list, $__nodes)
{
foreach ($__nodes as $node) {
array_push($__list, $node);
}
}
/**
* @throws Exception
*/
protected function processOpen()
{
/**
* Step 3. If OPEN is empty - throw Exception (we are actually done)
*/
$node = $this->popFirst($this->open);
/**
* Step 4. Select the first node on OPEN - move it to CLOSED
*/
array_push($this->closed, $node);
/**
* Step 5. If $node is a GOAL node - we are done - we skip this step because we are done
* only when $this->initialList / $this->open is empty
*/
/**
* Step 6. Expand $node by generating a set M of successors that are not already ancestors of
* $node in G. Install them into G.
*/
$successors = $this->expand($node);
$node->children = $successors;
/**
* Step 7. a) Establish a link from each successor to its parent
*/
$this->linkToParent($node);
/**
* Step 7. b) Add all successors to OPEN
*/
$this->pushToList($this->open, $successors);
/**
* Step 8. We skip this because we do not do any re-ordering on the graph
*/
/**
* Step 9. Go back to Step 3
*/
$this->processOpen();
}
/**
* @throws ErrorException
*/
protected function build()
{
if (sizeof($this->initialList) <= 0) {
throw new ErrorException('Bad initial list');
}
/**
* Step 1. Create a Search graph containing only the start node - put it on a list called OPEN
*/
$startNode = $this->remove("R3", $this->initialList);
array_push($this->nodes, $startNode);
array_push($this->open, $startNode);
try {
/**
* Step 3. If OPEN is empty - throw Exception (we are actually done)
*/
$this->processOpen();
} catch (Exception $e) {
return $e->getMessage();
}
}
// public function createNode($file, $className, $extendClass = null) {
//
// $node = new Node($file, $className);
//
// if ($extendClass) {
// $parent = new Node('', $extendClass);
// array_push($node['parents'], $parent);
// }
//
// return $node;
// }
//
// /**
// * @throws ErrorException
// */
// public function addNode($file, $className, $extendClassName)
// {
// if ($className === null) {
// throw new ErrorException("classname cannot be null");
// }
//
// echo "size of graph is " . sizeof($this->nodes) . "\n";
//
// $node = $this->createNode($file, $className, $extendClassName);
//
// array_push($this->nodes, $node);
// }
//
// public function sort()
// {
//
// echo "sorting graph";
//
// $baseClasses = [];
//
// $extendClasses = [];
//
// foreach ($this->nodes as $node) {
//
// if ($node['name'] === 'R3') {
//
// // skip R3 - it is the main parent of everything
//
// array_push($newGraph, $node);
//
// continue;
// }
//
// if (sizeof($node['parents']) === 0) {
// array_push($baseClasses, $node);
// } else {
// array_push($extendClasses, $node);
// }
// }
//
// foreach ($baseClasses as $baseClass) {
// array_push($baseClass['parents'], $newGraph[0]);
// array_push($newGraph[0]['children'], $baseClass);
// }
//
// foreach ($extendClasses as $extendClass) {
//
// findRecursive($extendClass['name'], $newGraph);
//
//
//
// }
// }
}
class Node
{
public $file = '';
public $name = '';
public $parent = null;
public $children = null;
function __construct(
$__file,
$__name,
$__parent = null,
$__children = null
)
{
$this->file = $__file;
$this->name = $__name;
$this->parent = $__parent;
$this->children = $__children;
}
}

View File

@ -2,6 +2,7 @@
<?php
include "utils.php";
include "graph.php";
function from_camel_case($input) {
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
@ -520,6 +521,69 @@ function generateMethods($file, $tokens)
}
$nodeList = [];
/**
* @throws ErrorException
*/
function buildGraph($file)
{
echo "loading file $file\n";
global $nodeList;
$fn = fopen($file, "r");
$line = '';
$found = false;
while (!feof($fn) && !$found) {
$line = fgets($fn);
if (preg_match('/^class\s+/', $line)) {
$found = true;
break;
}
}
if ($found) {
// echo $line . "\n";
$matches = [];
$result = preg_match('/^class\s+(.*?)(\s+extends\s+(.*?)\s+|\s+?{)/', $line, $matches);
if ($result === false) {
throw new ErrorException('Could not match');
}
$extends = null;
if (sizeof($matches) === 4) {
$class = $matches[1];
$extends = $matches[3];
} else if (sizeof($matches) === 3) {
$class = $matches[1];
} else {
throw new ErrorException('Unhandled case');
}
$node = new Node(
$file,
$class,
$extends
);
array_push($nodeList, $node);
} else {
echo "not found\n";
}
fclose($fn);
}
global $files;
foreach ($files as $file) {
@ -603,9 +667,17 @@ foreach ($files as $file) {
deleteSavedFile($saveFile);
exit(0);
}
} else if ($argv[2] == 'build-graph') {
buildGraph($file);
}
}
if ($argv[2] == 'build-graph') {
$graph = new Graph(
$nodeList
);
}
exit(0);
?>