3

我有一个用 PHP 解决的 1 级方程组。方程比变量多,但方程不比变量少。

该系统如下所示。n 个方程,m 个变量,变量是 x[i],其中 'i' 取值从 1 到 m。系统可能有解决方案,也可能没有。m 最大为 100,n 最大为 ~5000(千)。

我将不得不解决数千个这样的方程组。速度可能是个问题,但我现在正在寻找一种用 PHP 编写的算法。

a[1][1] * x[1] + a[1][2] * x[2] + ... + a[1][m] * x[m] = number 1
a[2][1] * x[1] + a[2][2] * x[2] + ... + a[2][m] * x[m] = number 2
...
a[n][1] * x[1] + a[n][2] * x[2] + ... + a[n][m] * x[m] = number n

有克拉默规则可以做到这一点。我可以制作 1 个系数方阵,使用 Cramer 规则求解系统(通过计算矩阵的行列式),然后我应该检查未使用方程中的值。我相信我可以自己尝试 Cramer,但我正在寻找更好的解决方案。

这是计算科学的问题, http ://en.wikipedia.org/wiki/Computational_science#Numerical_simulations 我知道有一些复杂的算法可以解决我的问题,但我不知道哪个会做,哪个最好对于我的情况。一个算法会比仅仅通过演示的理论更好地使用我。

我的问题是,有人知道用 PHP 编写的类、脚本、代码来解决 1 级线性方程组吗?或者,我可以尝试 API 或 Web 服务,最好是免费的,付费的也可以。

谢谢

4

4 回答 4

2

我正是需要这个,但我找不到行列式函数,所以我自己做了一个。Cramer 规则函数也是如此。也许它会帮助某人。

/**
 * $matrix must be 2-dimensional n x n array in following format
 * $matrix = array(array(1,2,3),array(1,2,3),array(1,2,3))
 */
function determinant($matrix = array()) {
    // dimension control - n x n
    foreach ($matrix as $row) {
        if (sizeof($matrix) != sizeof($row)) {
            return false;
        }
    }
    // count 1x1 and 2x2 manually - rest by recursive function
    $dimension = sizeof($matrix);
    if ($dimension == 1) {
        return $matrix[0][0];
    }
    if ($dimension == 2) {
        return ($matrix[0][0] * $matrix[1][1] - $matrix[0][1] * $matrix[1][0]);
    }
    // cycles for submatrixes calculations
    $sum = 0;
    for ($i = 0; $i < $dimension; $i++) {
        // for each "$i", you will create a smaller matrix based on the original matrix
        // by removing the first row and the "i"th column.
        $smallMatrix = array();
        for ($j = 0; $j < $dimension - 1; $j++) {
            $smallMatrix[$j] = array();
            for ($k = 0; $k < $dimension; $k++) {
                if ($k < $i) $smallMatrix[$j][$k] = $matrix[$j + 1][$k];
                if ($k > $i) $smallMatrix[$j][$k - 1] = $matrix[$j + 1][$k];
            }
        }
        // after creating the smaller matrix, multiply the "i"th element in the first
        // row by the determinant of the smaller matrix.
        // odd position is plus, even is minus - the index from 0 so it's oppositely
        if ($i % 2 == 0){
            $sum += $matrix[0][$i] * determinant($smallMatrix);
        } else {
            $sum -= $matrix[0][$i] * determinant($smallMatrix);
        }
    }
    return $sum;
}
/**
 * left side of equations - parameters:
 * $leftMatrix must be 2-dimensional n x n array in following format
 * $leftMatrix = array(array(1,2,3),array(1,2,3),array(1,2,3))
 * right side of equations - results:
 * $rightMatrix must be in format
 * $rightMatrix = array(1,2,3);
 */
function equationSystem($leftMatrix = array(), $rightMatrix = array()) {
    // matrixes and dimension check
    if (!is_array($leftMatrix) || !is_array($rightMatrix)) {
        return false;
    }
    if (sizeof($leftMatrix) != sizeof($rightMatrix)) {
        return false;
    }
    $M = determinant($leftMatrix);
    if (!$M) {
        return false;
    }
    $x = array();
    foreach ($rightMatrix as $rk => $rv) {
        $xMatrix = $leftMatrix;
        foreach ($rightMatrix as $rMk => $rMv) {
            $xMatrix[$rMk][$rk] = $rMv;
        }
        $x[$rk] = determinant($xMatrix) / $M;
    }
    return $x;
}
于 2016-12-08T12:44:16.313 回答
1

维基百科应该有伪代码,用于将表示您的方程的矩阵简化为简化的行梯形形式。一旦矩阵采用这种形式,您就可以遍历行以找到解决方案。

有一个未维护的 PEAR 包可以节省您编写代码的工作量。

另一个问题是您主要关注的是“宽”系统(变量多于方程,通常有许多可能的解)还是“窄”系统(方程多于变量,通常没有解),因为最佳策略取决于在这种情况下,狭窄的系统可能会受益于使用线性回归技术,例如最小二乘法

于 2012-06-21T13:00:32.563 回答
1

这个包使用高斯消除。我发现它对更大的矩阵(即更多的变量/方程)执行得很快。

于 2018-03-20T12:14:36.603 回答
0

这里有一个基于 JAMA 的真正优秀的包:http ://www.phpmath.com/build02/JAMA/docs/index.php

我已经将它用于简单的线性,以用于高度复杂的多元线性回归(在此基础上编写我自己的 Backwards Stepwise MLR 函数)。非常全面,希望能满足您的需求。

当然,速度可以被认为是一个问题。但是当我在 BSMLR 计算中交叉引用结果时,它可以很好地处理和匹配 SPSS。

于 2012-06-21T13:48:54.677 回答