/** * Check whether another node is near by the their identifier * * @param Node $otherNode * @return bool */ public function isNear(Node $otherNode) { $otherIdentifier = $otherNode->getIdentifier(); if ($otherIdentifier->getSize() != $this->identifier->getSize()) { return false; } $differences = 0; for ($i = 0; $i < $this->dimensions; $i++) { if ($otherIdentifier[$i] != $this->identifier[$i]) { $differences++; } if ($differences > 1) { return false; } } return true; }
/** * Recursive search step * * @param Node $currentNode * @param array $unavailable * @param array $path * @param WeightedNodeCollection $wNodes * @return array */ public function step(Node $currentNode, array $unavailable, array $path, WeightedNodeCollection $wNodes = null) { $currentString = $currentNode->getStringIdentifier(); $neighbors = $currentNode->computeNeighbors(); $exploredPaths = array(); $randomChoice = mt_rand(0, $this->dimensions - 1); $randomCount = 0; $randomAttempts = 0; $unavailable[] = $currentString; // Use weight information when available if (!is_null($wNodes) && $wNodes->hasStatisticsFor($currentString)) { $randomChoice = array_search($wNodes->getNode($currentString)->getBiasedNeighborChoice(), $neighbors); } foreach ($neighbors as $neighborString) { // Randomization if ($this->isRandomized()) { if ($randomChoice != $randomCount) { $randomCount++; continue; } $randomCount++; if (in_array($neighborString, $unavailable)) { $randomChoice = mt_rand(0, $this->dimensions - 1); $randomAttempts++; $randomCount = 0; // Give up if it is a dead end if ($randomAttempts > $this->dimensions) { break; } continue; } } elseif (in_array($neighborString, $unavailable)) { continue; } // Recursively navigate into the node $neighbor = new Node($this->dimensions, $neighborString); // Clone paths $neighborPath = array_merge($path); // Add path taken $neighborPath[] = array($currentString, $neighborString); // Add this node and other neighbors $neighborUnavailable[] = $neighbor->getStringIdentifier(); $otherNeighbors = array_diff($neighbors, array($neighborString)); $neighborUnavailable = array_merge($unavailable, array($currentString), $otherNeighbors); $newPath = $this->step($neighbor, $neighborUnavailable, $neighborPath); $exploredPaths[] = $newPath; } /*echo "\nExplored: " . count($exploredPaths) . "\n"; echo "Current: " . $currentString . "\n"; echo "Neighbors: \n"; print_r($neighbors); echo "Unavailable: \n"; print_r($unavailable);*/ // Find largest path explored $largestPathLength = 0; $largestPath = $path; foreach ($exploredPaths as $exploredPath) { $length = count($exploredPath); if ($length > $largestPathLength) { $largestPath = $exploredPath; $largestPathLength = $length; } } return $largestPath; }