damn dope graph build based on A* search
parent
7234726501
commit
f6adda0a7b
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
?>
|
Loading…
Reference in New Issue