r3-v2/graph.php

265 lines
5.3 KiB
PHP
Raw Normal View History

<?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;
}
}