public function getSolution()
 {
     $rootNode = new Node();
     $initialNode = new Node(['active' => true, 'content' => $this->getInitialNodeContent(), 'optimistic_bound' => $this->getInitialNodeOptimisticBound(), 'pessimistic_bound' => $this->getInitialNodePessimisticBound()]);
     $rootNode->addChild($initialNode);
     $activeNodes = [$initialNode];
     $currentBestFullNode = $initialNode;
     $i = 0;
     while ($activeNodes) {
         $i++;
         if ($i == 202) {
             $a = 2;
         }
         $this->_logEvent('step_begin', ['root_node' => $rootNode, 'active_nodes' => $activeNodes, 'current_best_full_node' => $currentBestFullNode]);
         $branchingNode = $this->_getBestNodeFrom($activeNodes);
         $branchingNode->setActive(false);
         $this->_logEvent('step_branching_begin', ['root_node' => $rootNode, 'branching_node' => $branchingNode]);
         $children = $this->_generateChildrenOf($branchingNode);
         $branchingNode->setChildren($children);
         $this->_logEvent('step_branching_children_generated', ['root_node' => $rootNode, 'branching_node' => $branchingNode, 'children_generated' => $children]);
         foreach ($branchingNode->getChildren() as $newNode) {
             // if new node is better (or has better evaluation) than current best node
             if ($this->_compareNodes($newNode, $currentBestFullNode) > -1 && $this->_nodeIsCorrect($newNode)) {
                 if ($this->_nodeIsCompleteSolution($newNode)) {
                     $currentBestFullNode = $newNode;
                 } else {
                     $newNode->setActive(true);
                 }
             } else {
                 $newNode->setActive(false);
             }
         }
         // get active nodes
         //  taking into account that nodes that were activated on previous steps (when they had best evaluation that solution on that step)
         //   CAN BECAME INACTIVE (due to solution on this step is better than their evaluations)
         //
         //   also we deactivate them if they don't satisfy some special node limitations (for PDP they are 3D loading constraints)
         $activeNodes = [];
         foreach ($rootNode->getActiveChildrenRecursive() as $node) {
             if ($this->_compareNodes($node, $currentBestFullNode) === 1) {
                 $activeNodes[] = $node;
             } else {
                 $newNode->setActive(false);
             }
         }
         $this->_logEvent('step_end', ['root_node' => $rootNode, 'active_nodes' => $activeNodes, 'children' => $children, 'current_best_full_node' => $currentBestFullNode]);
     }
     return $currentBestFullNode;
 }
 protected function _generateChildrenOf($node)
 {
     $result = [];
     if (!$this->_nodeIsCompleteSolution($node)) {
         $newPointSequences = $this->_generateNestedPointSequences($node);
         foreach ($newPointSequences as $newPointSequence) {
             if ($this->canLoad($newPointSequence)) {
                 $path = new Path(['points' => $newPointSequence]);
                 $newNode = new Node(['content' => $path]);
                 $newNode->setOptimisticBound($this->getEvaluator()->getBound($path, Evaluator::BOUND_TYPE_OPTIMISTIC));
                 $result[] = $newNode;
             }
         }
     }
     return $result;
 }