项目说明
该项目计算了马应该有多少食物,这是基于大量的变量。用户输入有关每匹马和首选饲料的信息。每种饲料都含有多种维生素和营养素。
1匹马使用多种饲料。
我们拥有什么
我们有特定马需要的每种营养素的最小值和最大值。
我们有一种或多种不同类型饲料的含量,每种饲料可能含有约20-30种不同的营养素和维生素。我们也有价格,并希望用它来省钱。
(当时只计算一匹马)
示例
我们使用A,B和C来代表营养素。
马需要:(A,B,C)MIN(30,7,9)MAX(35,9,17)
Feed 1包含:(A,B,C)VALUES(16,2,3)
Feed 2包含:(A,B,C)VALUES(0,4,9)
工作解决方案是2 * Feed1和1 * Feed2。
问题
我希望系统根据每种营养素的最小/最大值计算完美平衡,并保持尽可能低的价格。
工作解决方案
如果我首先计算每种饲料的最高可能量,则可以随机化,直到它看起来有效。然后,如果用户不完美,用户将能够更改金额。
<?php
function randomizerLoop(){
foreach($feeds as $feed){
$max['A'] = floor($horse_max['A']/$feed['A']);
$max['B'] = floor($horse_max['B']/$feed['B']);
$max['C'] = floor($horse_max['C']/$feed['C']);
$maxRand = MIN($max['A'], $max['B'], $max['C']);
$amounts[$feed['id']] = rand(0, $maxRand);
}
return $amounts;
}
?>
此代码将继续尝试,直到获得工作余额,而不是使用一些很酷的计算来在第一次尝试时找到余额。
我只需要了解如何在没有rand()
的情况下解决它。
更多信息
每个用户都可以添加无数马匹,但只能计算当时的一匹马(目前)。
还可以添加无数个Feed(由用户定义),每个Feed可以有20-30个变量。根据解决方案,这可能需要为每次自动计算限制Feed。
如果我们使用20个不同的Feed,每个Feed有20-30个变量,以及我们在int中定义数量而不仅仅是布尔值时,会有很多组合。
答案 0 :(得分:5)
这是linear programming问题。
MIN MAX
A 30 35
B 7 9
C 9 17
A B C
Feed1 16 2 3
Feed2 0 4 9
让食物包含x个feed1和y个feed2。根据你的问题:
30<16*x+0*y<35
=> 30<16x<35
使用ceil()
将30除以16,这将给出u x(即2)。之后你有3&lt; 4y&lt; 5,类似地使用ceil()
,你会得到y = 1.
现在考虑你的项目,
对于大量的饲料,很难计算出这么多的方程式。
我们应该使用矩阵来简化。上面给出的方程式的martix将是: -
A * B = C
|16 0| | x | | 30 |
|2 4| | y | = | 7 |
|3 9| | 9 |
现在使用Lapack::pseudoInverse()来计算矩阵A的逆矩阵并将其乘以C. 然后简单地将矩阵B中x和y的值等同于答案并使用ceil()。
答案 1 :(得分:4)
您要做的是尝试每个Feed的每个组合。让我们假设有5种类型的Feed。您已经知道如何计算每种Feed类型的最大值。所以,我假设你有类似的东西:
$feeds_cost = array of costs for each feed
$feeds_ingredient_A = array of how much ingredient A each feed has
$feeds_ingredient_B = array of how much ingredient B each feed has
$feeds_ingredient_C = array of how much ingredient C each feed has
$feeds_max = array of maximum quantity of each feed allowed
现在,对于5种类型,您想尝试数量{0,0,0,0,0},{0,0,0,0,1},{0,0,0,0,2} ... {$ feeds_max [0],$ feeds_max [1],$ feeds_max [2],$ feeds_max [3],$ feeds_max [4]}。对于每个数量集,您需要:1。确保数量满足最低要求。 2.如果满足最低要求,则计算成本。
因此,此时,您需要满足最低要求的每个数量的成本,但不超过最大要求。您无需存储所有这些内容。保持两个变量:$ best_quantities(每个Feed的计数数组)和$ best_cost。如果数量在满足要求的同时成本更低,则替换$ best_quantities和$ best_cost。
除了踩过所有数量之外,一切都是微不足道的。这真的不是很难。您维护正在递增的索引。最初,它为零,但它会达到最高的Feed索引(如果您有5个Feed,则为4)。增量函数是:
function increment_counts($feeds_max, $quantities, $index)
{
if($index>sizeof($quantities)) return null;
$quantities[$index]++;
if($quantities[$index] > $feeds_max[$index])
{
$quantities[$index]=0;
return increment_counts($feeds_max, $quantities, $index+1);
}
return $quantities;
}
假设我正确地输入了我的头顶,它将计算数量。您可以通过递增索引0并使用返回值替换当前数量来继续调用它。当它返回null时,你就完成了。
我确信我至少做过一次疏忽,但这就是解决这个问题的方法。
答案 2 :(得分:3)
我会专注于MIN值,以便最大限度地降低成本。在任何情况下,建议方法的全部要点是满足某些目标,这些目标可以根据需要变化(例如:迫使营养物E&amp; G至少得到MIN和MAX之间的半值)。 / p>
基本结构由三个环形成:一个主要通过所有营养素;和两个内部尝试饲料之间的所有可能组合。
NUTRIENT A
Trying feed1 until reaching minimum (because feed2 is zero).
Best so far: 2*feed1=32A.
NUTRIENT B
Starting from 2*feed1=4B, +feed2 reaches minimum.
Best so far: 2*feed1+feed2=8B.
NUTRIENT C
Starting from 2*feed1+feed2=15C which is fine already.
Best so far: 2*feed1+feed2=15C.
这种方法的更高级版本将返回检查(例如,在第一时刻达到目标的情况下,如营养素C发生的情况)是否可能有更好的替代方案。无论如何,这种实施的复杂性和组合的数量会明显更高。
我认为这是一种相当适应性和准确的方法。为基本版本实现算法并不太困难(但也不是太简单;这就是为什么我还没有在这里编写它)并且应该提供相当好的准确性和速度。在对其进行测试并了解其性能之后,您可能会开始考虑进一步改进它(例如,通过重新分析某些案例或考虑非MIN目标)。