[英]PHP - Difficult math calculation
項目描述
該項目計算了馬應該有多少食物,這是基於大量的變量。 用戶輸入有關每匹馬和首選飼料的信息。 每種飼料都含有多種維生素和營養素。
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()
情況下解決它。
更多信息
每個用戶將能夠添加無數的馬匹,但只能計算當時的一匹馬(目前)。
還可以添加無數個饋送(由用戶定義),每個饋送可以有20-30個變量。 根據解決方案,這可能需要為每次自動計算限制Feed。
如果我們使用20個不同的提要,每個提要20-30個變量,以及我們在int中定義數量而不僅僅是布爾值時,會有很多組合。
這是線性編程問題。
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,這將給出ux(即2)。 之后你有3 <4y <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()。
你想要做的是嘗試每種飼料的每種組合。 讓我們假設有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時,你就完成了。
我確信我至少做過一次疏忽,但這就是我要解決這個問題的方法。
我將重點關注MIN值,以便最大限度地降低成本。 在任何情況下,建議方法的全部要點是滿足某些目標,這些目標可能根據需要變化(例如:強制營養物E&G至少得到MIN和MAX之間的半值)。
基本結構由三個環形成:一個主要通過所有營養素; 和兩個內部嘗試飼料之間的所有可能組合。
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目標)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.