我写了一个 程序 DiophantusMin , 用 数值方法 求解 丢翻图方程组 的 最小解 。
项目地址 : https://github.com/kelin-xycs/DiophantusMin 。
进入 项目页面 后 点击 右边绿色 的 “Clone or download” 按钮 就可以下载 项目文件 了 。 项目中 只有一个 程序文件 DiophantusMin.html , 用 Html5 + javascript 写的, 用 浏览器 打开 就可以运行 。
算法 是 跨越逼近法, 算法 和 原理 见 《二元隐函数 数值求解》 https://www.cnblogs.com/KSongKing/p/12109699.html 。
丢番图方程组 是 不定方程组, 求 整数解 。 DiophantusMin 只 求 最小解 , 因为是 数值方法, 所以 严格的说, 是 未知数 绝对值 尽可能小 的 近似解 。
程序 会用 很多组 整数 去 代入 方程 尝试匹配, 每组整数 代入方程 后 计算 方程等式左边和右边 的 差 的 绝对值, 这个 差 的 绝对值 称为 diff, 表示 该组 整数 对 方程 的 满足程度, diff 越小, 满足方程 的 程度 越高, diff 越大, 满足方程 的 程度 越低 。
程序 会 将 diff 最小 的 一组 整数 作为 最终输出 的 解 。
因为是 方程组, 所以这里说的 diff 是 综合 方程组 中 各个 方程 的 diff 得出 的 diff, 规则 是 取 各个方程 的 diff 中 最大的 一个 diff 作为 方程组 的 diff 。
方程组 用 javascript 表示, 每个 方程 用 一个 函数 表示, 函数间 用 逗号隔开, 函数 返回 方程等式左边和右边的差, 程序会取差的绝对值作为 diff, 各方程最大的 diff 作为方程组的 diff, diff 最小的一组解就是最终输出的解 。
程序界面 里 默认 设定 了一个 方程组, 可以 直接 求解 试试 。
至于 最小解 的 “最小”, 这里并没有 去 求 多组 解 来 排序 得出 最小解, 这里的 做法 很简单, 就是 把 代入方程 尝试匹配 的 整数 的 范围 设定在 ( -100 , 100 ) 区间 内, 取 这个 区间 内 diff 最小 的 整数组合, 这样 差不多 就是 最小解 了 , 当然, 这是 近似 的, 而且 这是 针对 程序界面 上 默认设定 的 方程组 的 。
把 代入方程 尝试匹配 的 整数 的 范围 设定在 ( -100 , 100 ) 区间 内 这个 是 通过 匹配设定 设定 的 , 程序界面 上 默认 的 匹配设定 是 2 轮 匹配, 第 1 轮 步长 10, 步数 10, 第 2 轮 步长 1, 步数 10 。 这个 运行程序以后, 在 程序界面 上可以看到 。
匹配 的 初始值 是 0, 这是 写死 在 程序 里的, 用 初始值 加上 步长 * 步数 就得到 每一次 匹配 的 整数 。 对于 多个 未知数, 会通过 排列组合 产生 每一次 匹配 的 整数组合 。
因为 不同 的 方程(组) 的 解 的 分布规律 不一样, 所以 , 需要 设定 适当 的 步长 、步数 、进行多少轮匹配 , 才能 求得 足够 精确 的 解 。
匹配次数 和 步数 的 未知数个数 次方 成 正比, 就是说, 设 步数 为 m, 未知数个数 为 n, 则 匹配次数 和 m^n 成正比 。
所以, 当 未知数 个数 很多时, 匹配次数 很大, 时间复杂度 很大, 计算量 很大 。 可以采用 并行计算 大规模并行计算 超级计算机 来 应对 计算量 的 问题 , 未来 的 网格计算 也可以 用于 这个 方面 。
我在 知乎 《东方学帝不定方程组最小解有无系统解法?》 https://www.zhihu.com/question/365887404 里的 回答 :
我在 百度贴吧 民科吧 发了 一个 帖 《丢翻图方程组 最小解 计算机 数值求解》 http://tieba.baidu.com/p/6439347267 , 初步实现了 丢番图方程组 的 数值求解 , 这是一个 简单 的 程序, 但提出了 基本思想 和 实现了 基本算法, 是一个 demo, 也可以算是一个 内核, 未来 可在此 基础上 改写 和 扩展 为 成熟的, 可以适应 各种方程复杂情况 的 计算软件 。