C# 取函数的负数<;双[],双>;

C# 取函数的负数<;双[],双>;,c#,algorithm,math,func,C#,Algorithm,Math,Func,我有一个数学函数-exp{-(x-1)²}-exp{-0.5*(y-2)²},它通过函数及其导数被传递到BFGS算法中 Func<double[], double> f = (x) => Math.Exp(-Math.Pow(x[0] - 1, 2)) + Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)); Func<double[], double[]> g = (x) => new double[] { /

我有一个数学函数
-exp{-(x-1)²}-exp{-0.5*(y-2)²}
,它通过函数及其导数被传递到BFGS算法中

Func<double[], double> f = (x) => 
    Math.Exp(-Math.Pow(x[0] - 1, 2)) + Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2));

Func<double[], double[]> g = (x) => new double[] 
{
    // df/dx = -2 * e^(-(x - 1)²)(x - 1).
    -2 * Math.Exp(-Math.Pow(x[0] - 1, 2)) * (x[0] - 1),

    // df/dy = -e^(-1/2(y - 2)²) * (y - 2).
    -Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)) * (x[1] - 2)
};
我的问题是,我怎么能仅仅否定
this.Function
/
this.Gradient
对象?我在上面所做的将抛出一个
StackOverflowException

谢谢你抽出时间


编辑。带函数声明

[TestMethod]
公共无效LBFGSMaximisationTest()
{
//假设我们想要找到函数的最大值:
//f(x,y)=exp{-(x-1)²}+exp{-(y-2)²/2}。
//首先,我们需要将函数写为命名
//方法、匿名方法或作为lambda函数。
函数f=(x)=>
Math.Exp(-Math.Pow(x[0]-1,2))+Math.Exp(-0.5*Math.Pow(x[1]-2,2));
//现在,我们需要写出它的梯度,这就是
//一阶偏导数del_f/del_x的向量。
//g(x,y)={delf/delx,delf/dely}。
Func g=(x)=>new double[]
{
//df/dx=-2*e^(-x-1)²)(x-1)。
-2*Math.Exp(-Math.Pow(x[0]-1,2))*(x[0]-1),
//df/dy=-e^(-1/2(y-2)²)*(y-2)。
-数学表达式(-0.5*数学功率(x[1]-2,2))*(x[1]-2)
};
//最后,我们可以创建L-BFGS解算器,将函数作为参数传递。
随机r=新系统随机源(0,真);
BroydenFletcherGoldfarbShanno lbfgs=新BroydenFletcherGoldfarbShanno(
变量数:2,函数:f,梯度:g,随机:r);
//然后最小化函数。
double maxValue=lbfgs.Maximize();
...
是的,它将:

f = (x) => -this.Function(x);
this.Function = f;
假设
函数
是类级别的
函数
,那么您基本上是在编写:

this.Function = (x) => -this.Function(x);
是的,这会爆炸。这是因为
This.Function
是通过捕获的作用域延迟的。我怀疑你的意思是:

Func oldFunc=this.Function;
this.Function=(x)=>-oldFunc(x);

现在我们将旧函数捕获到一个委托中,并使用该捕获的委托而不是递归调用。

您不显示
函数
声明的位置。这很重要。您能显示一下吗?我相信
This.function(x)
不会捕获您期望的函数-相反,我认为它使用了新的值,例如,you'r doing function=-function,它再次调用function,等等。是的,我以前没有这样做过,它也没有像您期望的那样工作…感谢Marc,我认为在我上面展示的尝试中,将创建一个“新”对象这样就避免了那个讨厌的循环引用。在这种情况下,我将查找捕获的范围。谢谢你的时间。马克,在梯度的情况下,有两个独立的表达式(对于两个不同的方向),我如何去否定它们?
[TestMethod]
public void LBFGSMaximisationTest()
{
    // Suppose we would like to find the maximum of the function:
    // f(x, y) = exp{-(x - 1)²} + exp{-(y - 2)²/2}.
    // First we need write down the function either as a named
    // method, an anonymous method or as a lambda function.
    Func<double[], double> f = (x) =>
    Math.Exp(-Math.Pow(x[0] - 1, 2)) + Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2));

    // Now, we need to write its gradient, which is just the
    // vector of first partial derivatives del_f / del_x.
    // g(x, y) = { del f / del x, del f / del y }.
    Func<double[], double[]> g = (x) => new double[] 
    {
        // df/dx = -2 * e^(-(x - 1)²)(x - 1).
        -2 * Math.Exp(-Math.Pow(x[0] - 1, 2)) * (x[0] - 1),

        // df/dy = -e^(-1/2(y - 2)²) * (y - 2).
        -Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)) * (x[1] - 2)
    };

    // Finally, we can create the L-BFGS solver, passing the functions as arguments.
    Random r = new SystemRandomSource(0, true);
    BroydenFletcherGoldfarbShanno lbfgs = new BroydenFletcherGoldfarbShanno(
        numberOfVariables: 2, function: f, gradient: g, random: r);

    // And then minimize the function.
    double maxValue = lbfgs.Maximize();
    ...
f = (x) => -this.Function(x);
this.Function = f;
this.Function = (x) => -this.Function(x);
Func<double[], double> oldFunc = this.Function;
this.Function = (x) => -oldFunc(x);