Php 通过1000'的最佳循环方式;价值取向

Php 通过1000'的最佳循环方式;价值取向,php,math,mathematical-optimization,Php,Math,Mathematical Optimization,我需要找到x的值,其中两个结果的方差(考虑到x)最接近于0。问题是,唯一的方法是循环使用所有可能的x值。等式使用货币,因此我必须以1美分的增量进行检查 这可能会更容易: $previous_var = null; $high_amount = 50; for ($i = 0.01; $i <= $high_amount; $i += 0.01) { $val1 = find_out_1($i); $val2 = find_out_2(); $var = vari

我需要找到x的值,其中两个结果的方差(考虑到x)最接近于0。问题是,唯一的方法是循环使用所有可能的x值。等式使用货币,因此我必须以1美分的增量进行检查

这可能会更容易:

$previous_var = null;
$high_amount = 50;

for ($i = 0.01; $i <= $high_amount; $i += 0.01) {
    $val1 = find_out_1($i);
    $val2 = find_out_2();

    $var = variance($val1, $val2);

    if ($previous_var == null) {
        $previous_var = $var;
    }

    // If this variance is larger, it means the previous one was the closest to 
    // 0 as the variance has now started increasing
    if ($var > $previous_var) {
        $l_s -= 0.01;
        break;
    }
}

$optimal_monetary_value = $i;
$previous\u var=null;
$high_金额=50;
对于($i=0.01;$i$previous_var){
$l_s-=0.01;
打破
}
}
$optimal_monetary_value=$i;

我觉得有一个数学公式可以让“每一分钱循环”更为理想?它适用于较小的值,但如果您开始使用1000作为$high\u值,则需要花费相当多的时间来计算。

根据代码中的注释,听起来您需要类似于平分搜索的东西,但有点不同:

function calculate_variance($i) {
  $val1 = find_out_1($i);
  $val2 = find_out_2();

  return variance($val1, $val2);
}

function search($lo, $loVar, $hi, $hiVar) {
  // find the midpoint between the hi and lo values
  $mid = round($lo + ($hi - $lo) / 2, 2);
  if ($mid == $hi || $mid == $lo) {
    // we have converged, so pick the better value and be done
    return ($hiVar > $loVar) ? $lo : $hi;
  }
  $midVar = calculate_variance($mid);
  if ($midVar >= $loVar) {
    // the optimal point must be in the lower interval
    return search($lo, $loVar, $mid, $midVar);
  } elseif ($midVar >= $hiVar) {
    // the optimal point must be in the higher interval
    return search($mid, $midVar, $hi, $hiVar);
  } else {
    // we don't know where the optimal point is for sure, so check
    // the lower interval first
    $loBest = search($lo, $loVar, $mid, $midVar);
    if ($loBest == $mid) {
      // we can't be sure this is the best answer, so check the hi
      // interval to be sure
      return search($mid, $midVar, $hi, $hiVar);
    } else {
      // we know this is the best answer
      return $loBest;
    }
  }
}

$optimal_monetary_value = search(0.01, calculate_variance(0.01), 50.0, calculate_variance(50.0));
这假设方差在远离最佳点时单调增加。换句话说,如果最佳值是
O
,那么对于所有
X
计算方差(X)>=计算方差(Y)>=计算方差(O)
(所有
翻转时也是如此)。代码中的注释和编写方式使它看起来像是真的。如果这不是真的,那么你真的不可能做得比你所拥有的更好。/p pBe意识到这不如对分搜索好。有一些病理输入会使其花费线性时间而不是对数时间(例如,如果所有值的方差相同)。如果您可以将code计算方差(X)>=计算方差(Y)>=计算方差(O)
的要求改进为
计算方差(X)>计算方差(Y)>计算方差(O)
,通过检查
$mid
的方差如何与
$mid+0.01
的方差进行比较,并使用该值确定要检查的间隔,可以在所有情况下将其改进为对数


此外,你可能需要小心使用货币进行数学运算。您可能想要使用整数(即,所有数学运算都用美分而不是美元)或使用精确的数字。

根据代码中的注释,听起来您想要类似于对分搜索的东西,但有点不同:

function calculate_variance($i) {
  $val1 = find_out_1($i);
  $val2 = find_out_2();

  return variance($val1, $val2);
}

function search($lo, $loVar, $hi, $hiVar) {
  // find the midpoint between the hi and lo values
  $mid = round($lo + ($hi - $lo) / 2, 2);
  if ($mid == $hi || $mid == $lo) {
    // we have converged, so pick the better value and be done
    return ($hiVar > $loVar) ? $lo : $hi;
  }
  $midVar = calculate_variance($mid);
  if ($midVar >= $loVar) {
    // the optimal point must be in the lower interval
    return search($lo, $loVar, $mid, $midVar);
  } elseif ($midVar >= $hiVar) {
    // the optimal point must be in the higher interval
    return search($mid, $midVar, $hi, $hiVar);
  } else {
    // we don't know where the optimal point is for sure, so check
    // the lower interval first
    $loBest = search($lo, $loVar, $mid, $midVar);
    if ($loBest == $mid) {
      // we can't be sure this is the best answer, so check the hi
      // interval to be sure
      return search($mid, $midVar, $hi, $hiVar);
    } else {
      // we know this is the best answer
      return $loBest;
    }
  }
}

$optimal_monetary_value = search(0.01, calculate_variance(0.01), 50.0, calculate_variance(50.0));
这假设方差在远离最佳点时单调增加。换句话说,如果最佳值是
O
,那么对于所有
X
计算方差(X)>=计算方差(Y)>=计算方差(O)
(所有
翻转时也是如此)。代码中的注释和编写方式使它看起来像是真的。如果这不是真的,那么你真的不可能做得比你所拥有的更好。/p pBe意识到这不如对分搜索好。有一些病理输入会使其花费线性时间而不是对数时间(例如,如果所有值的方差相同)。如果您可以将code计算方差(X)>=计算方差(Y)>=计算方差(O)
的要求改进为
计算方差(X)>计算方差(Y)>计算方差(O)
,通过检查
$mid
的方差如何与
$mid+0.01
的方差进行比较,并使用该值确定要检查的间隔,可以在所有情况下将其改进为对数


此外,你可能需要小心使用货币进行数学运算。您可能想要使用整数(即,用美分而不是美元进行所有数学运算)或使用精确的数字。

如果您对目标函数的行为一无所知,除了尝试所有可能的值之外,没有其他方法

相反,如果你保证最小值是唯一的,黄金分割法会很快收敛。这是斐波那契搜索的一个变体,已知它是最优的(需要最少数量的函数求值)


您的函数可能具有不同的属性,这些属性需要其他算法。

如果您对目标函数的行为一无所知,那么除了尝试所有可能的值之外,没有其他方法

相反,如果你保证最小值是唯一的,黄金分割法会很快收敛。这是斐波那契搜索的一个变体,已知它是最优的(需要最少数量的函数求值)


您的函数可能具有调用其他算法的不同属性。

为什么不实现二进制搜索

<?php
$high_amount    = 50;
// computed val2 is placed outside the loop
// no need te recalculate it each time
$val2           = find_out_2();
$previous_var   = variance(find_out_1(0.01), $val2);

$start              = 0;
$end                = $high_amount * 100;
$closest_variance   = NULL;
while ($start <= $end) {
    $section    = intval(($start + $end)/2);
    $cursor     = $section / 100;
    $val1       = find_out_1($cursor);
    $variance   = variance($val1, $val2);

    if ($variance <= $previous_var) {
        $start = $section;
    }
    else {
        $closest_variance   = $cursor;
        $end                = $section;
    }
}

if (!is_null($closest_variance)) {
    $closest_variance -= 0.01;
}

为什么不实施二进制搜索呢

<?php
$high_amount    = 50;
// computed val2 is placed outside the loop
// no need te recalculate it each time
$val2           = find_out_2();
$previous_var   = variance(find_out_1(0.01), $val2);

$start              = 0;
$end                = $high_amount * 100;
$closest_variance   = NULL;
while ($start <= $end) {
    $section    = intval(($start + $end)/2);
    $cursor     = $section / 100;
    $val1       = find_out_1($cursor);
    $variance   = variance($val1, $val2);

    if ($variance <= $previous_var) {
        $start = $section;
    }
    else {
        $closest_variance   = $cursor;
        $end                = $section;
    }
}

if (!is_null($closest_variance)) {
    $closest_variance -= 0.01;
}

读到这篇文章时,我意识到我应该提高我的数学。。。但你能举例说明产出吗;你能更清楚地理解这道数学题吗?由于你所有的函数(
find\u out\u 1
find\u 2
variance
)都是匿名的,我认为除了暴力之外,我们不可能提出更好的解决方案。你在这里把这种差异称为什么?读到这篇文章时,我意识到我应该改进我的数学。。。但你能举例说明产出吗;你能更清楚地理解这道数学题吗?使用所有功能(
find_out_1
find_out_2
variance
)作为匿名者,我认为除了暴力之外,我们不可能提出更好的解决方案。你在这里把差异称为什么?这个过程确实不完美,因为存在一些配置,你不知道选择哪个子区间。当你一次考虑四个点而不是三个点时,这个问题就解决了。在每一次迭代中,您拒绝三次迭代中的一次间隔。实现了最优的区间大小缩减策略