mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 09:48:40 +00:00
Implement weighted job scheduling
This commit is contained in:
parent
4e3678d498
commit
a504f6bd0e
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package phpOMS\Algorithm\JobScheduling
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Algorithm\JobScheduling;
|
||||
|
||||
/**
|
||||
* Job for scheduling
|
||||
*
|
||||
* @package phpOMS\Algorithm\JobScheduling
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Job
|
||||
{
|
||||
/**
|
||||
* Value of the job
|
||||
*
|
||||
* @var float
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private float $value = 0.0;
|
||||
|
||||
/**
|
||||
* Start time of the job
|
||||
*
|
||||
* @var \DateTime
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private \DateTime $start;
|
||||
|
||||
/**
|
||||
* End time of the job
|
||||
*
|
||||
* @var \DateTime
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private ?\DateTime $end = null;
|
||||
|
||||
/**
|
||||
* Name of the job
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private string $name = '';
|
||||
|
||||
/**
|
||||
* Cosntructor.
|
||||
*
|
||||
* @param float $value Value of the job
|
||||
* @param \DateTime $start Start time of the job
|
||||
* @param null|\DateTime $end End time of the job
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(float $value, \DateTime $start, ?\DateTime $end, string $name = '')
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of the job
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getValue() : float
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get start time of the job
|
||||
*
|
||||
* @return \DateTime
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getStart() : \DateTime
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get end time of the job
|
||||
*
|
||||
* @return \DateTime
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getEnd() : ?\DateTime
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the job
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getName() : string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.4
|
||||
*
|
||||
* @package phpOMS\Algorithm\JobScheduling
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://orange-management.org
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\Algorithm\JobScheduling;
|
||||
|
||||
/**
|
||||
* Job scheduling algorithm with no overlapping jobs
|
||||
*
|
||||
* @package phpOMS\Algorithm\JobScheduling
|
||||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class Weighted
|
||||
{
|
||||
/**
|
||||
* Sort jobs by end date.
|
||||
*
|
||||
* @param Jobs $j1 Job 1
|
||||
* @param Jobs $j2 Job 2
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function sortByEnd(Job $j1, Job $j2) : int
|
||||
{
|
||||
if ($j1->getEnd() === null && $j2->getEnd() !== null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($j1->getEnd() === null && $j2->getEnd() === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($j1->getEnd() !== null && $j2->getEnd() === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $j1->getEnd()->getTimestamp() <=> $j2->getEnd()->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a none-conflicting job that comes befor a defined job
|
||||
*
|
||||
* @param Job[] $jobs List of jobs
|
||||
* @param int $pivot Job to find the previous job to
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function binarySearch(array $jobs, int $pivot) : int
|
||||
{
|
||||
$lo = 0;
|
||||
$hi = $pivot - 1;
|
||||
|
||||
while ($lo <= $hi) {
|
||||
$mid = (int) (($lo + $hi) / 2);
|
||||
|
||||
if ($jobs[$mid]->getEnd() !== null
|
||||
&& $jobs[$mid]->getEnd()->getTimestamp() <= $jobs[$pivot]->getStart()->getTimestamp()
|
||||
) {
|
||||
if ($jobs[$mid + 1]->getEnd() !== null
|
||||
&& $jobs[$mid + 1]->getEnd()->getTimestamp() <= $jobs[$pivot]->getStart()->getTimestamp()
|
||||
) {
|
||||
$lo = $mid + 1;
|
||||
} else {
|
||||
return $mid;
|
||||
}
|
||||
} else {
|
||||
$hi = $mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximize the value of the job execution without overlapping jobs
|
||||
*
|
||||
* @param Job[] $jobs Jobs to filter
|
||||
*
|
||||
* @return Job[]
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function solve(array $jobs) : array
|
||||
{
|
||||
$n = \count($jobs);
|
||||
|
||||
if ($n < 2) {
|
||||
return $jobs;
|
||||
}
|
||||
|
||||
\usort($jobs, [self::class, 'sortByEnd']);
|
||||
|
||||
$valueTable = [$jobs[0]->getValue()];
|
||||
|
||||
$resultTable = [];
|
||||
$resultTable[0] = [$jobs[0]];
|
||||
|
||||
for ($i = 1; $i < $n; ++$i) {
|
||||
$value = $jobs[$i]->getValue();
|
||||
$jList = [$jobs[$i]];
|
||||
$l = self::binarySearch($jobs, $i);
|
||||
|
||||
if ($l != -1) {
|
||||
$value += $valueTable[$l];
|
||||
$jList = \array_merge($resultTable[$l], $jList);
|
||||
}
|
||||
|
||||
if ($value > $valueTable[$i - 1]) {
|
||||
$valueTable[$i] = $value;
|
||||
$resultTable[$i] = $jList;
|
||||
} else {
|
||||
$valueTable[$i] = $valueTable[$i - 1];
|
||||
$resultTable[$i] = $resultTable[$i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return $resultTable[$n - 1];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user