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