mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-05 12:08:42 +00:00
Finish knapsack implementation
This commit is contained in:
parent
5ee0e67512
commit
4e3678d498
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* PHP Version 7.4
|
* PHP Version 7.4
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knappsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|
@ -13,12 +13,12 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Algorithm\Knappsack;
|
namespace phpOMS\Algorithm\Knapsack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backpack for the Knappsack problem
|
* Backpack for the Knapsack problem
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knappsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @link https://orange-management.org
|
* @link https://orange-management.org
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
|
|
@ -93,6 +93,18 @@ class Backpack
|
||||||
return $this->cost;
|
return $this->cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the max allowed costs for the items
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getMaxCost() : float
|
||||||
|
{
|
||||||
|
return $this->maxCost;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get items
|
* Get items
|
||||||
*
|
*
|
||||||
|
|
@ -108,16 +120,17 @@ class Backpack
|
||||||
/**
|
/**
|
||||||
* Add item to backpack
|
* Add item to backpack
|
||||||
*
|
*
|
||||||
* @param Item $item Item
|
* @param Item $item Item
|
||||||
|
* @param mixed $quantity Quantity of the item
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function addItem(Item $item) : void
|
public function addItem(Item $item, $quantity = 1) : void
|
||||||
{
|
{
|
||||||
$this->items[] = $item;
|
$this->items[] = ['item' => $item, 'quantity' => $quantity];
|
||||||
$this->value += $item->getValue();
|
$this->value += $item->getValue() * $quantity;
|
||||||
$this->cost += $item->getCost();
|
$this->cost += $item->getCost() * $quantity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
87
Algorithm/Knapsack/Bounded.php
Normal file
87
Algorithm/Knapsack/Bounded.php
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Algorithm\Knapsack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bounded knapsack algorithm
|
||||||
|
*
|
||||||
|
* This algorithm only works for integer cost, values and quantities!
|
||||||
|
*
|
||||||
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class Bounded
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Fill the backpack with items
|
||||||
|
*
|
||||||
|
* This algorithm only works for integer cost, values and quantities!
|
||||||
|
*
|
||||||
|
* @param array $items Items to fill the backpack with ['item' => Item, 'quantity' => ?]
|
||||||
|
* @param Backpack $backpack Backpack to fill
|
||||||
|
*
|
||||||
|
* @return Backpack
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public static function solve(array $items, Backpack $backpack) : Backpack
|
||||||
|
{
|
||||||
|
$n = \count($items);
|
||||||
|
$maxCost = (int) $backpack->getMaxCost();
|
||||||
|
$mm = \array_fill(0, ($maxCost + 1), 0);
|
||||||
|
$m = [];
|
||||||
|
$m[0] = $mm;
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $n; ++$i) {
|
||||||
|
$m[$i] = $mm;
|
||||||
|
|
||||||
|
for ($j = 0; $j <= $maxCost; ++$j) {
|
||||||
|
$m[$i][$j] = $m[$i - 1][$j];
|
||||||
|
|
||||||
|
for ($k = 1; $k <= $items[$i - 1]['quantity']; $k++) {
|
||||||
|
if ($k * ((int) $items[$i - 1]['item']->getCost()) > $j) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$v = $m[$i - 1][$j - $k * ((int) $items[$i - 1]['item']->getCost())] + $k * ((int) $items[$i - 1]['item']->getValue());
|
||||||
|
|
||||||
|
if ($v > $m[$i][$j]) {
|
||||||
|
$m[$i][$j] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = 0;
|
||||||
|
for ($i = $n, $j = $maxCost; $i > 0; --$i) {
|
||||||
|
$s = 0;
|
||||||
|
$v = $m[$i][$j];
|
||||||
|
|
||||||
|
for ($k = 0; $v !== $m[$i - 1][$j] + $k * ((int) $items[$i - 1]['item']->getValue()); ++$k) {
|
||||||
|
$s++;
|
||||||
|
$j -= (int) $items[$i - 1]['item']->getCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($s > 0) {
|
||||||
|
$backpack->addItem($items[$i - 1]['item'], $s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $backpack;
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Algorithm/Knapsack/Continuous.php
Normal file
61
Algorithm/Knapsack/Continuous.php
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Algorithm\Knapsack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous knapsack algorithm
|
||||||
|
*
|
||||||
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class Continuous
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Fill the backpack with items
|
||||||
|
*
|
||||||
|
* @param array $items Items to fill the backpack with ['item' => Item, 'quantity' => ?]
|
||||||
|
* @param Backpack $backpack Backpack to fill
|
||||||
|
*
|
||||||
|
* @return Backpack
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public static function solve(array $items, Backpack $backpack) : Backpack
|
||||||
|
{
|
||||||
|
usort($items, function($a, $b) {
|
||||||
|
return $a['item']->getValue() / $a['item']->getCost() < $b['item']->getValue() / $b['item']->getCost();
|
||||||
|
});
|
||||||
|
|
||||||
|
$availableSpace = $backpack->getMaxCost();
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
if ($availableSpace <= 0.0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$backpack->addItem(
|
||||||
|
$item['item'],
|
||||||
|
$quantity = \min($item['quantity'], $availableSpace / $item['item']->getCost())
|
||||||
|
);
|
||||||
|
|
||||||
|
$availableSpace -= $quantity * $item['item']->getCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $backpack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* PHP Version 7.4
|
* PHP Version 7.4
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knappsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Algorithm\Knappsack;
|
namespace phpOMS\Algorithm\Knapsack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item in the knappsack
|
* Item in the Knapsack
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knappsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @license OMS License 1.0
|
* @license OMS License 1.0
|
||||||
* @link https://orange-management.org
|
* @link https://orange-management.org
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
|
|
@ -30,7 +30,7 @@ class Item
|
||||||
* @var float
|
* @var float
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private $value = 0.0;
|
private float $value = 0.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cost of the item
|
* Cost of the item
|
||||||
|
|
@ -38,7 +38,15 @@ class Item
|
||||||
* @var float
|
* @var float
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private $cost = 0.0;
|
private float $cost = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the item
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private string $name = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cosntructor.
|
* Cosntructor.
|
||||||
|
|
@ -48,10 +56,11 @@ class Item
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct(float $value, float $cost)
|
public function __construct(float $value, float $cost, string $name = '')
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
$this->cost = $cost;
|
$this->cost = $cost;
|
||||||
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -77,4 +86,16 @@ class Item
|
||||||
{
|
{
|
||||||
return $this->cost;
|
return $this->cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the item
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getName() : string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user