Unity中C#实现单纯形法时While循环致编辑器崩溃求助
问题排查与修复方案
一、核心无限循环原因:单纯形法迭代逻辑错误
你的Unity编辑器冻结本质是迭代后目标行(第0行)始终存在负数,导致count永远不为0,无法触发break,根源是表格更新的核心公式和比率测试逻辑写错了:
1. 非Pivot行更新公式完全错误
当前代码里非Pivot行的更新逻辑不符合单纯形法规则:
simplexTable[i, pivotValueIndex] = 0; for (int j = 0; j <= numberOfConstraints + 3; j++) { if (j != pivotValueIndex) { simplexTable[i, j] = simplexTable[i, j] - simplexTable[i, j] * (simplexTable[pivotRow, j] / pivotCell); } }
正确逻辑:非Pivot行的每个元素应该是 新值 = 原值 - (该行Pivot列的原始值) * (标准化后的Pivot行对应列值),而且不能提前把Pivot列设为0,要先保存原始值再计算:
else { // 先保存当前行Pivot列的原始值,避免被覆盖后无法计算 float rowPivotOriginal = simplexTable[i, pivotValueIndex]; for (int j = 0; j <= numberOfConstraints + 3; j++) { // Pivot行已经除以pivotCell标准化过,直接相乘即可 simplexTable[i, j] = simplexTable[i, j] - rowPivotOriginal * simplexTable[pivotRow, j]; } }
2. 比率测试(Ratio Test)逻辑漏洞
当前ratioTestArr只初始化了第0位为0,其余元素默认是0,会导致程序错误选中目标行(第0行)作为Pivot行——而Pivot行必须从约束行(i≥1)中选择,这会彻底破坏迭代逻辑,导致永远无法收敛。
修复方案:
float[] ratioTestArr = new float[numberOfConstraints]; // 初始化所有元素为无穷大,确保只会从约束行中选Pivot行 Array.Fill(ratioTestArr, float.PositiveInfinity); for (int i = 1; i < pivotColumn.Length; i++) { if (simplexTable[i, pivotValueIndex] > 0) { ratioTestArr[i] = simplexTable[i, numberOfConstraints + 3] / simplexTable[i, pivotValueIndex]; } } // 此时最小比率对应的行一定是约束行 int pivotRow = Array.IndexOf(ratioTestArr, ratioTestArr.Min());
二、数组越界问题修复
你标记的IndexOutOfRangeException,大概率是pivotValueArr的长度不匹配表格列数导致的。当前pivotValueArr长度是numberOfConstraints +4,但如果表格实际列数超过这个值,就会越界,建议直接用表格的列数初始化:
float[] pivotValueArr = new float[simplexTable.GetColumns()];
同时检查simplexTable.GetColumns()的实现是否正确返回实际列数,避免循环条件失效。
三、其他优化与防护
- 恢复
maximised变量的赋值,保持逻辑完整性:
if (count == 0) { maximised = true; Debug.Log("已找到最优解"); break; }
- 添加迭代次数限制,避免极端情况的无限循环:
int iterationCount = 0; int maxIterations = 100; // 可根据问题复杂度调整 while (!maximised && iterationCount < maxIterations) { iterationCount++; // ... 原有循环逻辑 } if (iterationCount >= maxIterations) { Debug.LogError("达到最大迭代次数,可能存在无解或逻辑错误"); }
- 校验
numberOfConstraints的正确性:它应该等于simplexTable.GetRows() -1(第0行是目标行,其余是约束行),如果两者不匹配,会导致循环逻辑混乱。
四、内存问题排查
4GB内存确实偏小,但Unity如果是内存不足,通常会先弹出警告而非直接无响应。优先修复上述逻辑错误后,若仍有问题,可通过Window > Analysis > Profiler查看CPU和内存占用,确认是否是循环导致的CPU满负载,或用简单测试用例(比如2个约束的线性规划问题)验证。
内容的提问来源于stack exchange,提问作者Avneet K
相关产品推荐
相关产品推荐

