簡體   English   中英

PHP - 困難的數學計算

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM