Tôi có một vấn đề tối ưu hóa phi tuyến tính với các ràng buộc. Nó có thể được giải quyết trong Microsoft Excel với phần bổ trợ Solver, nhưng tôi gặp sự cố khi sao chép trong C#.Làm cách nào để mô phỏng chức năng Bộ giải của Microsoft Excel (GRG phi tuyến) trong C#?
Sự cố của tôi được hiển thị trong following spreadsheet. Tôi đang giải quyết vấn đề cổ điển A x = b nhưng với báo trước rằng tất cả các thành phần của x phải không âm. Vì vậy, thay vì sử dụng đại số tuyến tính chuẩn, tôi sử dụng Solver với ràng buộc không âm, giảm thiểu tổng của các khác biệt bình phương và nhận được một giải pháp hợp lý. Tôi đã cố gắng sao chép điều này trong C# bằng cách sử dụng Microsoft Solver Foundation hoặc Solver SDK. Tuy nhiên, dường như tôi không thể tìm được ở đâu với MSF vì tôi không thể tìm ra cách xác định mục tiêu và với Solver SDK, tôi luôn lấy lại trạng thái "tối ưu" và giải pháp cho tất cả 0 mà chắc chắn không phải là địa phương tối thiểu.
Đây là mã của tôi cho Solver SDK:
static double[][] A = new double[][] { new double[] { 1, 0, 0, 0, 0 }, new double[] { 0.760652602, 1, 0, 0, 0 }, new double[] { 0.373419404, 0.760537565, 1, 0, 0 }, new double[] { 0.136996731, 0.373331934, 0.760422587, 1, 0 }, new double[] { 0.040625222, 0.136953801, 0.373244464, 0.76030755, 1 } };
static double[][] b = new double[][] { new double[] { 2017159 }, new double[] { 1609660 }, new double[] { 837732.8125 }, new double[] { 330977.3125 }, new double[] { 87528.38281 } };
static void Main(string[] args)
{
using(Problem problem = new Problem(Solver_Type.Minimize, 5, 0))
{
problem.VarDecision.LowerBound.Array = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0 };
problem.VarDecision.UpperBound.Array = new double[] { Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF };
problem.Evaluators[Eval_Type.Function].OnEvaluate += new EvaluateEventHandler(SumOfSquaredErrors);
problem.ProblemType = Problem_Type.OptNLP;
problem.Solver.Optimize();
Optimize_Status status = problem.Solver.OptimizeStatus;
Console.WriteLine(status.ToString());
foreach(double x in problem.VarDecision.FinalValue.Array)
{
Console.WriteLine(x);
}
}
}
static Engine_Action SumOfSquaredErrors(Evaluator evaluator)
{
double[][] x = new double[evaluator.Problem.Variables[0].Value.Array.Length][];
for(int i = 0; i < x.Length; i++)
{
x[i] = new double[1] { evaluator.Problem.Variables[0].Value.Array[i] };
}
double[][] b_calculated = MatrixMultiply(A, x);
double sum_sq = 0.0;
for(int i = 0; i < b_calculated.Length; i++)
{
sum_sq += Math.Pow(b_calculated[i][0] - b[i][0], 2);
}
evaluator.Problem.FcnObjective.Value[0] = sum_sq;
return Engine_Action.Continue;
}
static double[][] MatrixMultiply(double[][] left, double[][] right)
{
if(left[0].Length != right.Length)
{
throw new ArgumentException();
}
double[][] sum = new double[left.Length][];
for(int i = sum.GetLowerBound(0); i <= sum.GetUpperBound(0); i++)
{
sum[i] = new double[right[i].Length];
}
for(int i = 0; i < sum.Length; i++)
{
for(int j = 0; j < sum[0].Length; j++)
{
for(int k = 0; k < right.Length; k++)
{
sum[i][j] += left[i][k] * right[k][j];
}
}
}
return sum;
}
tôi không có bất kỳ mã cho Microsoft Solver Foundation bởi vì tôi không nghĩ rằng chức năng mục tiêu có thể được viết trong một dòng duy nhất và nó doesn' t cho phép các đại biểu như Solver SDK thực hiện.
Vậy làm thế nào để hiển thị mã của bạn?Nếu bạn lấy lại tất cả 0 thì có lẽ bạn đang làm gì đó sai. –
Có bạn đi. Có thể đã thực hiện nó trước đây nhưng tôi phải viết một hàm nhân ma trận nhanh và dơ bẩn vì tôi đang sử dụng một lớp 'Matrix' độc quyền. –
muốn xem mã nền tảng giải của Microsoft – FistOfFury