diff --git a/Algorithm/Knappsack/Bounded.php b/Algorithm/Knappsack/Bounded.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/Algorithm/Knappsack/Continuous.php b/Algorithm/Knappsack/Continuous.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/Algorithm/Knappsack/Unbounded.php b/Algorithm/Knappsack/Unbounded.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/Algorithm/Knappsack/Backpack.php b/Algorithm/Knapsack/Backpack.php similarity index 71% rename from Algorithm/Knappsack/Backpack.php rename to Algorithm/Knapsack/Backpack.php index e4ac782dc..ec2faa859 100644 --- a/Algorithm/Knappsack/Backpack.php +++ b/Algorithm/Knapsack/Backpack.php @@ -4,7 +4,7 @@ * * PHP Version 7.4 * - * @package phpOMS\Algorithm\Knappsack + * @package phpOMS\Algorithm\Knapsack * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 @@ -13,12 +13,12 @@ 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 * @link https://orange-management.org * @since 1.0.0 @@ -93,6 +93,18 @@ class Backpack 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 * @@ -108,16 +120,17 @@ class Backpack /** * Add item to backpack * - * @param Item $item Item + * @param Item $item Item + * @param mixed $quantity Quantity of the item * * @return void * * @since 1.0.0 */ - public function addItem(Item $item) : void + public function addItem(Item $item, $quantity = 1) : void { - $this->items[] = $item; - $this->value += $item->getValue(); - $this->cost += $item->getCost(); + $this->items[] = ['item' => $item, 'quantity' => $quantity]; + $this->value += $item->getValue() * $quantity; + $this->cost += $item->getCost() * $quantity; } } diff --git a/Algorithm/Knapsack/Bounded.php b/Algorithm/Knapsack/Bounded.php new file mode 100644 index 000000000..b595220d5 --- /dev/null +++ b/Algorithm/Knapsack/Bounded.php @@ -0,0 +1,87 @@ + 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; + } +} \ No newline at end of file diff --git a/Algorithm/Knapsack/Continuous.php b/Algorithm/Knapsack/Continuous.php new file mode 100644 index 000000000..f874779d0 --- /dev/null +++ b/Algorithm/Knapsack/Continuous.php @@ -0,0 +1,61 @@ + 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; + } +} \ No newline at end of file diff --git a/Algorithm/Knappsack/Item.php b/Algorithm/Knapsack/Item.php similarity index 64% rename from Algorithm/Knappsack/Item.php rename to Algorithm/Knapsack/Item.php index 19d5c2cd7..7aff3d41c 100644 --- a/Algorithm/Knappsack/Item.php +++ b/Algorithm/Knapsack/Item.php @@ -4,7 +4,7 @@ * * PHP Version 7.4 * - * @package phpOMS\Algorithm\Knappsack + * @package phpOMS\Algorithm\Knapsack * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 @@ -12,12 +12,12 @@ */ 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 * @link https://orange-management.org * @since 1.0.0 @@ -30,7 +30,7 @@ class Item * @var float * @since 1.0.0 */ - private $value = 0.0; + private float $value = 0.0; /** * Cost of the item @@ -38,7 +38,15 @@ class Item * @var float * @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. @@ -48,10 +56,11 @@ class Item * * @since 1.0.0 */ - public function __construct(float $value, float $cost) + public function __construct(float $value, float $cost, string $name = '') { $this->value = $value; $this->cost = $cost; + $this->name = $name; } /** @@ -77,4 +86,16 @@ class Item { return $this->cost; } + + /** + * Get the name of the item + * + * @return string + * + * @since 1.0.0 + */ + public function getName() : string + { + return $this->name; + } }