Esempio n. 1
0
 /**
  * Calculate equivalent nodes
  *
  * Calculate groups of nodes, which are contained in their respective 
  * transitive reflexive closure in the automaton.
  *
  * Returns an automaton consisting of nodes, which each links to such a 
  * node group.
  * 
  * @param slCountingSingleOccurenceAutomaton $automaton 
  * @return void
  */
 protected function calculateEquivalencyAutomaton(slAutomaton $automaton)
 {
     $nodeValues = $automaton->getNodes();
     $nodes = array_keys($nodeValues);
     $nodeCount = count($nodes);
     $equivalent = array();
     $skip = array();
     // Find equivalence classes in automaton
     for ($i = 0; $i < $nodeCount; ++$i) {
         if (isset($skip[$i])) {
             continue;
         }
         $this->equivalenceClasses[$nodes[$i]] = array($nodes[$i]);
         $equivalent[$nodes[$i]] = $nodes[$i];
         for ($j = $i + 1; $j < $nodeCount; ++$j) {
             if (in_array($nodes[$i], $automaton->transitiveClosure($nodes[$j])) && in_array($nodes[$j], $automaton->transitiveClosure($nodes[$i]))) {
                 $this->equivalenceClasses[$nodes[$i]][] = $nodes[$j];
                 $equivalent[$nodes[$j]] = $nodes[$i];
                 // The mutal containment in eachs reflexive transitive
                 // closure is obviously symetric
                 $skip[$j] = true;
             }
         }
     }
     // Readd edges between equivalency classes based on source automaton
     $equivalencyAutomaton = new slAutomaton();
     foreach ($this->equivalenceClasses as $name => $nodes) {
         $equivalencyAutomaton->addNode($name);
         foreach ($nodes as $node) {
             foreach ($automaton->getOutgoing($node) as $dst) {
                 if ($name !== $equivalent[$dst]) {
                     $equivalencyAutomaton->addEdge($name, $equivalent[$dst]);
                 }
             }
         }
     }
     return $equivalencyAutomaton;
 }