Esempio n. 1
0
    public function __construct()
    {
        $this->queue = new \SplPriorityQueue();

        $this->timer = Loop\periodic(1, function () {
            $time = time();
            while (!$this->queue->isEmpty()) {
                $key = $this->queue->top();

                if (isset($this->expire[$key])) {
                    if ($time <= $this->expire[$key]) {
                        break;
                    }

                    unset($this->data[$key], $this->expire[$key], $this->ttl[$key]);
                }

                $this->queue->extract();
            }

            if ($this->queue->isEmpty()) {
                $this->timer->stop();
            }
        });

        $this->timer->stop();
        $this->timer->unreference();
    }
Esempio n. 2
0
 /**
  * @see QueueInterface::pop()
  */
 public function pop()
 {
     if (!$this->innerQueue->isEmpty()) {
         $eta = $this->innerQueue->top()->getEta();
         if (!$eta || $eta->getTimestamp() <= time()) {
             return $this->innerQueue->extract();
         }
     }
     return false;
 }
Esempio n. 3
0
 /**
  * {@inheritdoc}
  */
 public function pop()
 {
     if (!$this->queue->isEmpty()) {
         $this->queue->setExtractFlags(\SplPriorityQueue::EXTR_PRIORITY);
         $priority = $this->queue->top();
         if (time() + $priority[0] >= 0) {
             $this->queue->setExtractFlags(\SplPriorityQueue::EXTR_DATA);
             return $this->queue->extract();
         }
     }
     throw new NoItemAvailableException($this);
 }
Esempio n. 4
0
 /**
  * {@inheritdoc}
  */
 public function pop()
 {
     if ($this->queue->isEmpty()) {
         return;
     }
     $this->queue->setExtractFlags(\SplPriorityQueue::EXTR_PRIORITY);
     $priority = $this->queue->top();
     if (time() + $priority[0] >= 0) {
         $this->queue->setExtractFlags(\SplPriorityQueue::EXTR_DATA);
         return $this->queue->extract();
     }
 }
Esempio n. 5
0
 /**
  * 主循环
  * @see Events\EventInterface::loop()
  */
 public function loop()
 {
     $e = null;
     while (1) {
         // 如果有信号,尝试执行信号处理函数
         pcntl_signal_dispatch();
         $read = $this->_readFds;
         $write = $this->_writeFds;
         // 等待可读或者可写事件
         @stream_select($read, $write, $e, 0, $this->_selectTimeout);
         // 尝试执行定时任务
         if (!$this->_scheduler->isEmpty()) {
             $this->tick();
         }
         // 这些描述符可读,执行对应描述符的读回调函数
         if ($read) {
             foreach ($read as $fd) {
                 $fd_key = (int) $fd;
                 if (isset($this->_allEvents[$fd_key][self::EV_READ])) {
                     call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], array($this->_allEvents[$fd_key][self::EV_READ][1]));
                 }
             }
         }
         // 这些描述符可写,执行对应描述符的写回调函数
         if ($write) {
             foreach ($write as $fd) {
                 $fd_key = (int) $fd;
                 if (isset($this->_allEvents[$fd_key][self::EV_WRITE])) {
                     call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], array($this->_allEvents[$fd_key][self::EV_WRITE][1]));
                 }
             }
         }
     }
 }
Esempio n. 6
0
 /**
  * Executes any pending timers. Returns the number of timers executed.
  *
  * @return int
  *
  * @internal
  */
 public function tick() : int
 {
     $count = 0;
     $time = microtime(true);
     while (!$this->queue->isEmpty()) {
         list($timer, $timeout) = $this->queue->top();
         if (!$this->timers->contains($timer) || $timeout !== $this->timers[$timer]) {
             $this->queue->extract();
             // Timer was removed from queue.
             continue;
         }
         if ($this->timers[$timer] > $time) {
             // Timer at top of queue has not expired.
             return $count;
         }
         // Remove and execute timer. Replace timer if persistent.
         $this->queue->extract();
         if ($timer->isPeriodic()) {
             $timeout = $time + $timer->getInterval();
             $this->queue->insert([$timer, $timeout], -$timeout);
             $this->timers[$timer] = $timeout;
         } else {
             $this->timers->detach($timer);
         }
         // Execute the timer.
         $timer->call();
         ++$count;
     }
     return $count;
 }
Esempio n. 7
0
 /**
  * @see Events\EventInterface::loop()
  */
 public function loop()
 {
     $e = null;
     while (1) {
         // Calls signal handlers for pending signals
         pcntl_signal_dispatch();
         $read = $this->_readFds;
         $write = $this->_writeFds;
         // Waiting read/write/signal/timeout events.
         $ret = @stream_select($read, $write, $e, 0, $this->_selectTimeout);
         if (!$this->_scheduler->isEmpty()) {
             $this->tick();
         }
         if (!$ret) {
             continue;
         }
         foreach ($read as $fd) {
             $fd_key = (int) $fd;
             if (isset($this->_allEvents[$fd_key][self::EV_READ])) {
                 call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], array($this->_allEvents[$fd_key][self::EV_READ][1]));
             }
         }
         foreach ($write as $fd) {
             $fd_key = (int) $fd;
             if (isset($this->_allEvents[$fd_key][self::EV_WRITE])) {
                 call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], array($this->_allEvents[$fd_key][self::EV_WRITE][1]));
             }
         }
     }
 }
Esempio n. 8
0
 /**
  * Get the number of microseconds until the next timer watcher is due.
  * 
  * @return int or null when no timers are pending.
  */
 protected function nextTimeout()
 {
     $time = \microtime(true);
     while (!$this->scheduler->isEmpty()) {
         list($watcher, $scheduled) = $this->scheduler->top();
         if ($watcher->enabled && $watcher->scheduled === $scheduled) {
             return (int) \max(0, ($watcher->due - $time) * 1000000);
         }
     }
 }
Esempio n. 9
0
/**
 * Поиск самого дешёвого пути между двумя локациями
 * Для поиска используется алгоритм Дейкстры
 *
 * @see http://www.sitepoint.com/data-structures-4/
 *
 * @param array  $data   Массив с локациями и ценой проезда между ними [][src, dst, cost]
 * @param string $source Название исходного пункта
 * @param string $target Название конечного пункта
 *
 * @return SplStack
 */
function find_path(array $data, $source, $target)
{
    $graph = build_graph($data);
    // массив лучших цен кратчайшего пути для каждой локации
    $best_cost = [];
    // массив предыдущих локаций для каждой локации
    $prev_loc = array();
    // очередь из необработанных локаций
    $queue = new SplPriorityQueue();
    foreach ($graph as $src => $dst) {
        $best_cost[$src] = INF;
        // изначальные значения цен бесконечны
        $prev_loc[$src] = null;
        // предыдущие локации неизвестны
        foreach ($dst as $name => $cost) {
            // используем цену как приоритет в очереди
            $queue->insert($name, $cost);
        }
    }
    // цена поездки в исходный пункт = 0
    $best_cost[$source] = 0;
    while (!$queue->isEmpty()) {
        // получаем минимальную цену
        $u = $queue->extract();
        if (empty($graph[$u])) {
            continue;
        }
        // обрабатываем доступные маршруты для локации
        foreach ($graph[$u] as $v => $cost) {
            // альтернативная цена для маршрута
            $alt = $best_cost[$u] + $cost;
            if ($alt < $best_cost[$v]) {
                // обновляем минимальную цену для локации
                $best_cost[$v] = $alt;
                // добавляем локацию в массив предыдущих локаций
                $prev_loc[$v] = $u;
            }
        }
    }
    // ищем дешёвый путь и складываем его в стек
    $stack = new SplStack();
    $u = $target;
    $final_cost = 0;
    // проходим в обратном порядке от пункта назначения к исходному пункту
    while (isset($prev_loc[$u]) && $prev_loc[$u]) {
        $stack->push($u);
        $final_cost += $graph[$u][$prev_loc[$u]];
        $u = $prev_loc[$u];
    }
    $stack->push($source);
    return [$stack, $final_cost];
}
Esempio n. 10
0
File: App.php Progetto: koolkode/k1
 /**
  * {@inheritdoc}
  */
 public final function compileRoutes(RouteCompiler $compiler, RoutingContext $context) : array
 {
     $parsed = new \SplPriorityQueue();
     foreach ($this->routes as $route) {
         foreach ($route->compile($compiler) as list($priority, $depth, $route, $regex, $mapping)) {
             $parsed->insert(\array_merge([$regex, $depth, $priority, $route], $mapping), $priority);
         }
     }
     $result = [];
     while (!$parsed->isEmpty()) {
         $result[] = $parsed->extract();
     }
     return $result;
 }
Esempio n. 11
0
 /**
  * Поиск кратчайшего пути
  * @see https://www.youtube.com/watch?v=UA6aV1XJCGg
  */
 private function _shortestPath()
 {
     while (!$this->_nodeQueue->isEmpty()) {
         $u = $this->_nodeQueue->extract();
         if (!empty($this->_routes[$u])) {
             foreach ($this->_routes[$u] as $v => $cost) {
                 $newCost = $this->_destinations[$u] + $cost;
                 if ($newCost < $this->_destinations[$v]) {
                     $this->_destinations[$v] = $newCost;
                     $this->_predecessors[$v] = $u;
                 }
             }
         }
     }
 }
Esempio n. 12
0
 private function findNeighbors($type, $keywords, $id)
 {
     $queue = new SplPriorityQueue();
     $queue->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
     $cursor = $this->m->websites->find([]);
     foreach ($cursor as $doc) {
         if ($doc['_id'] != new MongoId($id)) {
             $d = $this->distance($type, $keywords, $doc['type'], $doc['keywords']);
             $queue->insert($doc, $d);
         }
     }
     $res = [];
     for ($i = 0; $i < 20 && !$queue->isEmpty(); $i++) {
         $res[] = $queue->extract();
     }
     return $res;
 }
Esempio n. 13
0
 /**
  * @return int Milliseconds until next timer expires or -1 if there are no pending times.
  */
 private function getTimeout()
 {
     while (!$this->timerQueue->isEmpty()) {
         list($watcher, $expiration) = $this->timerQueue->top();
         $id = $watcher->id;
         if (!isset($this->timerExpires[$id]) || $expiration !== $this->timerExpires[$id]) {
             $this->timerQueue->extract();
             // Timer was removed from queue.
             continue;
         }
         $expiration -= (int) (\microtime(true) * self::MILLISEC_PER_SEC);
         if ($expiration < 0) {
             return 0;
         }
         return $expiration;
     }
     return -1;
 }
Esempio n. 14
0
 /**
  * {@inheritdoc}
  */
 public final function compileRoutes(RouteCompiler $compiler, RoutingContext $context) : array
 {
     $ref = new \ReflectionClass(static::class);
     $parsed = new \SplPriorityQueue();
     foreach ($ref->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
         if ($method->isStatic() || !$method->hasReturnType()) {
             continue;
         }
         $type = (string) $method->getReturnType();
         if ($type !== Route::class && !\is_subclass_of($type, Route::class)) {
             continue;
         }
         $args = $context->container->populateArguments($method, [], new InjectionPoint(static::class));
         $route = $this->{$method->name}(...$args);
         foreach ($route->compile($compiler) as list($priority, $depth, $route, $regex, $mapping)) {
             $parsed->insert(\array_merge([$regex, $depth, $priority, $route], $mapping), $priority);
         }
     }
     $result = [];
     while (!$parsed->isEmpty()) {
         $result[] = $parsed->extract();
     }
     return $result;
 }
Esempio n. 15
0
 public function tokenize(string $input) : array
 {
     if (!$this->initialized) {
         $this->initialized = true;
         $this->initialize();
     }
     $types = [];
     $parts = [];
     $transform = [];
     foreach ($this->tokens as $k => list($v, $t)) {
         $types[] = $k;
         $parts[] = '(' . $v . ')';
         $transform[] = $t;
     }
     $sorter = new \SplPriorityQueue();
     foreach ($this->terminals as $k => list(, $terminal)) {
         $sorter->insert([$k, $terminal], strlen($terminal));
     }
     while (!$sorter->isEmpty()) {
         list($k, $terminal) = $sorter->extract();
         $types[] = $k;
         $parts[] = '(' . $terminal . ')';
         $transform[] = NULL;
     }
     $types[] = 'T_IDENTIFIER';
     $parts[] = '(' . $this->identifierPattern . ')';
     $transform[] = NULL;
     $regex = "~" . implode('|', $parts) . "~AS";
     $len = strlen($input);
     $offset = 0;
     $tokens = [];
     $line = 1;
     $pos = 1;
     $m = NULL;
     while (true) {
         if ($offset >= $len) {
             break;
         }
         if (!preg_match($regex, $input, $m, NULL, $offset)) {
             throw new \RuntimeException(sprintf('No matching token found at position: "%s"', substr($input, $offset, 10)));
         }
         $i = count($m) - 2;
         $type = $types[$i];
         $tlen = strlen($m[0]);
         if ($type === 'T_IDENTIFIER') {
             $key = strtolower($m[0]);
             if (isset($this->keywords[$key])) {
                 $keyword = $this->keywords[$key];
                 if (!$keyword[1] || $m[0] == $keyword[2]) {
                     $type = $keyword[0];
                     $m[0] = $keyword[2];
                 }
             }
         }
         if (empty($this->skip[$type])) {
             $tokens[] = $this->createToken($type, isset($transform[$i]) ? $transform[$i]($m[0]) : $m[0], $line, $pos, $offset + 1);
         }
         $offset += $tlen;
         $pos += $tlen;
         if (false !== strpos($m[0], "\n")) {
             $line += substr_count($m[0], "\n");
             $pos = strlen(substr($m[0], strrpos($m[0], "\n"))) + 1;
         }
     }
     return $tokens;
 }
Esempio n. 16
0
 /**
  * Получить самый дешевый маршрут
  *
  * @param string $from Начало маршрута
  * @param string $to Конец маршрута
  *
  * @throws \Exception
  *
  * @return array
  */
 public function getPath($from, $to)
 {
     /**
      * Массив с результатом
      */
     $result = [];
     /**
      * Массив кратчайших путей к каждому узлу
      */
     $d = [];
     /**
      * Массив "предшественников" для каждого узла
      */
     $pi = [];
     /**
      * Очередь всех неоптимизированных узлов
      */
     $queue = new SplPriorityQueue();
     foreach ($this->graph as $v => $adj) {
         /**
          * Устанавливаем изначальные расстояния как бесконечность
          */
         $d[$v] = INF;
         /**
          * Никаких узлов позади нет
          */
         $pi[$v] = null;
         foreach ($adj as $w => $cost) {
             /**
              * Воспользуемся ценой связи как приоритетом
              */
             $queue->insert($w, $cost);
         }
     }
     /**
      * Начальная дистанция на стартовом узле - 0
      */
     $d[$from] = 0;
     while (!$queue->isEmpty()) {
         /**
          * Извлечем минимальную цену
          */
         $u = $queue->extract();
         if (!empty($this->graph[$u])) {
             /**
              * Пройдемся по всем соседним узлам
              */
             foreach ($this->graph[$u] as $v => $cost) {
                 /**
                  * Установим новую длину пути для соседнего узла
                  */
                 $alt = $d[$u] + $cost;
                 /**
                  * Если он оказался короче
                  *   update minimum length to vertex установим как минимальное расстояние до этого узла
                  *   добавим соседа как предшествующий этому узла
                  */
                 if ($alt < $d[$v]) {
                     $d[$v] = $alt;
                     $pi[$v] = $u;
                 }
             }
         }
     }
     /**
      * Теперь мы можем найти минимальный путь используя обратный проход
      */
     $stack = new SplStack();
     $u = $to;
     $result['sum'] = 0;
     /**
      * Проход от целевого узла до стартового
      */
     while (isset($pi[$u]) && $pi[$u]) {
         $stack->push($u);
         /**
          * Добавим стоимость для предшествующих
          */
         $result['sum'] += $this->graph[$u][$pi[$u]];
         $u = $pi[$u];
     }
     /**
      * Стек будет пустой, если нет пути назад
      */
     if ($stack->isEmpty()) {
         throw new Exception('Нет пути из ' . $from . ' в ' . $to);
     } else {
         /**
          * Добавим стартовый узел и покажем весь путь в обратном (LIFO) порядке
          */
         $stack->push($from);
         foreach ($stack as $v) {
             $result['path'][] = $v;
         }
     }
     return $result;
 }
 public function shortestPath($source, $target)
 {
     // initialize Q, d and pi for all vertices
     $d = array();
     // array of best estimates of shortest path to each vertex
     $pi = array();
     // array of predecessors for each vertex
     $Q = new SplPriorityQueue();
     // queue of all unoptimized vertices
     foreach ($this->graph as $v => $adj) {
         $d[$v] = INF;
         // set initial distance to "infinity"
         $pi[$v] = null;
         // no known predecessors yet
         foreach ($adj as $w => $cost) {
             // use the edge cost as the priority
             $Q->insert($w, $cost);
         }
     }
     // initial distance at source is 0
     $d[$source] = 0;
     while (!$Q->isEmpty()) {
         // extract min cost
         $u = $Q->extract();
         if (!empty($this->graph[$u])) {
             // "relax" each adjacent vertex
             foreach ($this->graph[$u] as $v => $cost) {
                 // alternate route length to adjacent neighbor
                 $alt = $d[$u] + $cost;
                 // if alternate route is shorter
                 if ($alt < $d[$v]) {
                     $d[$v] = $alt;
                     // update minimum length to vertex
                     $pi[$v] = $u;
                     // add neighbor to predecessors for vertex
                 }
             }
         }
     }
     // we can now find the shortest path using reverse iteration
     $S = new SplStack();
     // construct the shortest path with a stack S
     $u = $target;
     $dist = 0;
     // traverse from target to source
     while (isset($pi[$u]) && $pi[$u]) {
         $S->push($u);
         $dist += $this->graph[$u][$pi[$u]];
         // add distance to next predecessor
         $u = $pi[$u];
     }
     // stack will be empty if there is no route back
     if ($S->isEmpty()) {
         echo "No route from {$source} to {$target}\n";
     } else {
         // add the source node and print the path in reverse (LIFO) order
         $S->push($source);
         echo "{$dist}:";
         $sep = '';
         foreach ($S as $v) {
             echo $sep, $v;
             $sep = '->';
         }
         echo "\n";
     }
 }
Esempio n. 18
0
 public function shortestPath($source, $target)
 {
     $shortPath = array();
     //масив найкоротших шляхів
     $prevNode = array();
     //масив попередників
     $queueNodes = new SplPriorityQueue();
     //черга всіх вузлів
     foreach ($this->graph as $node => $bondage) {
         $shortPath[$node] = INF;
         //встановлення початкових шляхів в безкінечність
         $prevNode[$node] = null;
         //вузлів позаду немає
         foreach ($bondage as $bondNode => $cost) {
             $queueNodes->insert($bondNode, $cost);
         }
     }
     // початкова дистанція на стартовому вузлі - 0
     $shortPath[$source] = 0;
     while (!$queueNodes->isEmpty()) {
         //вибір мінімальної вартості
         $node = $queueNodes->extract();
         if (!empty($this->graph[$node])) {
             //прохід по всім сусіднім вузлам
             foreach ($this->graph[$node] as $nameNode => $cost) {
                 //встановлення нової довжини шляху для сусіднього вузла
                 $alt = $shortPath[$node] + $cost;
                 //якщо вузол коротший
                 if ($alt < $shortPath[$nameNode]) {
                     $shortPath[$nameNode] = $alt;
                     //встановлюється як мінімальна відстань до вузла
                     $prevNode[$nameNode] = $node;
                     //додавання сусіда як попередника вузла
                 }
             }
         }
     }
     //використовуючи зворотній прохід, визначається мінімальний шлях
     $shortStack = new SplStack();
     //найкоротший шлях як стек
     $node = $target;
     $dist = 0;
     //прохід від цільового вузла до стартового
     while (isset($prevNode[$node]) && $prevNode[$node]) {
         $shortStack->push($node);
         $dist += $this->graph[$node][$prevNode[$node]];
         //додавання дистанції для попередників
         $node = $prevNode[$node];
     }
     //стек буде пустий, якщо нема шляху назад
     if ($shortStack->isEmpty()) {
         $this->res .= "Немає шляху із " . $source . " в " . $target;
     } else {
         //добавлення стартового вузла, виведення всього шляху
         $shortStack->push($source);
         $this->res .= "{$dist}:  ";
         $sep = '';
         foreach ($shortStack as $v) {
             $this->res .= $sep . $v;
             $sep = '->';
         }
     }
     return $this->res;
 }
Esempio n. 19
0
    foreach ($school_array as $key => $school) {
        $school_same = split(";", $school);
        $response = json_decode(file_get_contents('http://maps.googleapis.com/maps/api/distancematrix/json?origins=' . urlencode($home) . '&destinations=' . urlencode($school_same[0]) . '&mode=driving&language=nl-BE&sensor=false'));
        $distance = -(int) $response->rows[0]->elements[0]->distance->text;
        $pq->insert($school, $distance);
        $pref_array2[$id][$school] = $distance;
    }
    $pref_array[$id] = $pq;
}
$engage_array = [];
$avn_array = [];
$id_enagage = [];
while (count($engage_array) < count($school_array)) {
    foreach ($pref_array as $id => $pq) {
        if (!isset($id_enagage[$id]) || !$id_enagage[$id]) {
            if (!$pq->isEmpty()) {
                $top = $pq->top();
                if (!isset($engage_array[$top])) {
                    $engage_array[$top] = $id;
                    $id_enagage[$id] = true;
                    //echo "$top***$id<br>";
                } else {
                    $old = $engage_array[$top];
                    if (!isset($avnarray[$old])) {
                        $avnarray[$old] = avn($old, $conn, $pref_array2, $id_home);
                        //echo "###$avnarray[$old]<br>";
                    }
                    if (!isset($avnarray[$id])) {
                        $avnarray[$id] = avn($id, $conn, $pref_array2, $id_home);
                        //echo "!!!!!$avnarray[$id]<br>";
                    }
<?php

$pq = new SplPriorityQueue();
$pq->insert('Clear drains', 3);
$pq->insert('Feed cat', 4);
$pq->insert('Make tea', 5);
$pq->insert('Solve RC tasks', 1);
$pq->insert('Tax return', 2);
// This line causes extract() to return both the data and priority (in an associative array),
// Otherwise it would just return the data
$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
while (!$pq->isEmpty()) {
    print_r($pq->extract());
}