如何在Accord.NET中通过字符串动态实例化NonlinearObjectiveFunction
解决方案
原生C#实现方案(无外部运行时依赖,优先推荐)
你之前贴出的NonlinearObjectiveFunction(int numberOfVariables, Func<double[], double> function)构造函数本身不直接接受字符串,官方文档提到的字符串构造能力,本质是要你先把用户输入的数学表达式转换成该构造要求的Func<double[], double>委托类型,不需要依赖R或Matlab就能实现:
- 用
MathNet.Symbolics库完成用户输入字符串的解析、表达式编译、自动求梯度全流程,完全适配Accord.NET的入参要求。 - 示例代码如下:
// 提前安装NuGet包:MathNet.Symbolics using MathNet.Symbolics; using Accord.Optimization; // 示例:用户输入的目标函数、变量列表,可从WPF界面控件获取输入 string userInput = "100*(y-x^2)^2 + (1-x)^2"; string[] variables = new[] { "x", "y" }; // 解析人类可读的数学表达式 var expression = Infix.ParseOrThrow(userInput); // 编译为接受double数组的可执行委托,数组顺序和variables顺序对应(x对应input[0], y对应input[1]) var compiledFunc = Evaluate.Compile(variables, expression); Func<double[], double> objectiveFunction = input => compiledFunc(input); // 直接传入构造函数即可 var objective = new NonlinearObjectiveFunction(numberOfVariables: 2, function: objectiveFunction); // 如果需要梯度参数,也可以自动生成不需要用户手动输入 var gradientExpressions = variables.Select(v => Differentiate.Derivative(expression, v)).ToArray(); var compiledGradients = gradientExpressions.Select(exp => Evaluate.Compile(variables, exp)).ToArray(); Func<double[], double[]> gradientFunction = input => compiledGradients.Select(g => g(input)).ToArray(); // 带梯度的完整构造 var objectiveWithGradient = new NonlinearObjectiveFunction(2, objectiveFunction, gradientFunction);
该方案支持所有常规非线性函数(幂次、三角函数、指数、对数等),不需要依赖外部运行时,性能远高于调用R/Matlab的方案,适合桌面端WPF项目部署。
外部计算引擎方案(仅适合特殊场景)
如果你的用户需要用到R/Matlab特有的专业优化函数,可以用你提到的组件实现:
- R.NET方案:将用户输入的表达式转发给R进程计算返回结果,封装为符合要求的
Func<double[], double>委托即可,缺点是需要用户设备安装R运行时,响应延迟高。 - Matlab COM方案:逻辑和R.NET一致,依赖Matlab运行时,部署成本更高。
补充说明
Accord.NET 3.0+版本已经将原生字符串解析功能拆分到Accord.Math.Symbolic单独包,如果你不想引入MathNet,也可以安装该包后调用NonlinearObjectiveFunction.FromExpression()方法直接解析字符串生成目标函数对象。
内容的提问来源于stack exchange,提问作者Ana Ibrahim
相关产品推荐
相关产品推荐

