【问题标题】:Algorithm for linear equations with more solutions具有更多解的线性方程组的算法
【发布时间】:2013-03-22 12:32:07
【问题描述】:

有人可以帮助我解决模算术中的线性方程组(!)。我只需要“最小”的解决方案。最小意味着按字典顺序排列。

让我们拥有这个系统:
3x1+2x2=3
4x1+3x2+1x3+2x4=4
x 旁边的数字是索引。

我们使用模 5 的系统的矩阵(0 3 2 0 0 0 | 3
4 3 1 2 0 | 4

对此的最小解是 (0,4,0,1,0)。我必须编写一个算法来给我那个解决方案。 我在考虑蛮力,因为 p

PS:矩阵可以有很多种形式,比如:
3 2 4 0 0 | 3
4 3 1 2 1 | 4


1 2 0 0 0 | 3
3 0 3 0 0 | 3
4 3 1 2 3 | 4
等等

对不起我的英语,我来自亚洲。

编辑:我在考虑如何确定哪些变量是参数。但是想不通....

【问题讨论】:

  • 定义“最小”。 (1,0,0,0,0) 不是更小的解决方案吗?
  • 你的两个方程是否是 2x^2 + 3x = 3 和 2x^4+x^3+3x^2+4x=4 ???我没有得到你的解决方案(0,4,0,1,0)
  • @KlasLindbäck 对不起,已定义!:) @ 55K 不,它的 3x(index 1) +2x(index 2) 等等。
  • 高斯消元法应该与实数中的相同,但有一个关键区别:通常会尝试“除法”的地方,现在必须计算逆模 p 并进行乘法。

标签: c algorithm math


【解决方案1】:

啊,这到底是怎么回事,为什么不呢,给你吧

#include <stdio.h>

#define L 2
#define N 5
#define MOD 5

static int M[L][N] =
{       { 3, 2, 0, 0, 0 }
,       { 4, 3, 1, 2, 0 }
};

static int S[L] =
{       3, 4
};

static void init(int * s)
{
        int     i;
        for (i = 0; i < N; i++)
        {
                s[i] = 0;
        }
}

static int next(int * s)
{
        int     i, c;
        c = 1;
        for (i = N-1; i >= 0 && c > 0; i--)
        if ( (++s[i]) == MOD)
        {
                s[i] = 0;
        }
        else
        {
                c = 0;
        }
        return c == 0;
}

static int is_solution(int * s)
{
        int     i, j, sum;

        for (i = 0; i < L; i++)
        {
                sum = 0;
                for (j = 0; j < N; j++)
                {
                        sum += M[i][j]*s[j];
                }
                if (sum % MOD != S[i])
                {
                        return 0;
                }
        }
        return 1;
}

int main(void)
{
        int     s[N];

        init(s);
        do
        {
                if (is_solution(s))
                {
                        int     i;
                        for (i = 0; i < N; i++)
                        {
                                printf(" %d", s[i]);
                        }
                        printf("\n");
                        break;
                }
        } while (next(s));
        return 0;
}

【讨论】:

  • 它不起作用,例如 static int M[L][N] = { { 4, -2, 0, 0, 2 } , { 0, 0, -1, 4, 1 } }; 与 mod=3,并更改了 S[L]={4,0} - 我希望我确实得到了它应该是的
  • 好的,搞定了,但是我怎么知道方程组有没有解呢?
  • 如果没有解决方案,程序将打印无解决方案。请注意,如果您遗漏了最后一个 break,它将打印所有解决方案。
  • 这个时间复杂度是多少?我将有 0
  • 因为如果我用一个没有解的方程组运行它,它不会停止
【解决方案2】:

您可以将此视为线性代数和高斯消元模型中的一个问题。

您正试图找到 Mx = y mod p 的解。如有必要,通过添加 0'x = 0 的行从正方形 M 开始。现在使用高斯消去 mod p 将 M 尽可能地减少为上三角形式。您最终会得到一个方程组,例如

ax + by + cz = H

 dy + ez = G

但是在对角线上有一些零,可能是因为您用完了方程式,或者是因为所有方程式在特定列处都为零。如果您有 0z = 1 或类似的内容,则没有解决方案。如果不是,您可以像往常一样通过自下而上求解,并在不存在对角线上的 z 系数非零的方程时输入 z=0,从而得出可能的多种解决方案之一。

如果最重要的未知数对应于向量的底部,我认为这将产生字典上最小的答案。下面展示了如何获取任意解决方案并使其按字典顺序最小化,我认为您会发现它不会修改如上生成的解决方案。

现在看看http://en.wikipedia.org/wiki/Kernel_%28matrix%29。存在向量 n 的线性空间,使得 Mn = 0,并且方程的所有解的形式为 x + n,其中 n 是该空间中的向量 - 零空间 - 而 x 是特定解,例如就像你锻炼出来的那样。

你可以通过找到 Mn = 0 的解来计算零空间的基础,就像你找到 x 一样。找到对角线上没有非零条目的列,转到该列的对角线应该所在的行,将该列的未知数设置为 1,然后从那里向上移动矩阵,选择其他未知数你有一个 Mn = 0 的解。

请注意,您从中获得的所有向量在该向量的某个位置都有 1,在该向量下方有 0,并且在上方可能有非零条目。这意味着,如果您将它们的倍数添加到解决方案中,从最下方 1 的向量开始,后面的向量将永远不会干扰您之前添加的解决方案的分量,因为后面的向量总是为零在那里。

因此,如果您想找到字典上最小的解决方案,您可以安排一些事情,以便您首先使用具有字典上最大条目的空空间的基础。从任意解开始,并尽可能按字典顺序添加零空间向量,以减少解向量。您最终应该得到字典上最小的解向量 - 通过从零空间添加基向量的组合,可以从任何其他解中生成任何解,并且您可以从上述过程中看到它产生字典上最小的此类结果 -在每个阶段,最重要的组件都已尽可能小,任何替代品都必须在字典上更大。

【讨论】:

    猜你喜欢
    • 2018-09-23
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 2021-05-27
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多