在将 C# 转换为 F# 时处理 byref 和 out 参数
Handling byref and out params in translating C# to F#
有人可以帮助将以下 C# 示例代码从 Alglib 库翻译成 F# 吗?我无法在 Internet 上找到有关如何从 F# 使用它的任何示例。
public static void function1_grad(double[] x, ref double func, double[] grad, object obj)
{
// this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
// and its derivatives df/d0 and df/dx1
func = 100*System.Math.Pow(x[0]+3,4) + System.Math.Pow(x[1]-3,4);
grad[0] = 400*System.Math.Pow(x[0]+3,3);
grad[1] = 4*System.Math.Pow(x[1]-3,3);
}
public static int Main(string[] args)
{
//
// This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
// using LBFGS method.
//
// Several advanced techniques are demonstrated:
// * upper limit on step size
// * restart from new point
//
double[] x = new double[]{0,0};
double epsg = 0.0000000001;
double epsf = 0;
double epsx = 0;
double stpmax = 0.1;
int maxits = 0;
alglib.minlbfgsstate state;
alglib.minlbfgsreport rep;
// first run
alglib.minlbfgscreate(1, x, out state);
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits);
alglib.minlbfgssetstpmax(state, stpmax);
alglib.minlbfgsoptimize(state, function1_grad, null, null);
alglib.minlbfgsresults(state, out x, out rep);
System.Console.WriteLine("{0}", alglib.ap.format(x,2)); // EXPECTED: [-3,3]
// second run - algorithm is restarted
x = new double[]{10,10};
alglib.minlbfgsrestartfrom(state, x);
alglib.minlbfgsoptimize(state, function1_grad, null, null);
alglib.minlbfgsresults(state, out x, out rep);
System.Console.WriteLine("{0}", rep.terminationtype); // EXPECTED: 4
System.Console.WriteLine("{0}", alglib.ap.format(x,2)); // EXPECTED: [-3,3]
System.Console.ReadLine();
return 0;
}
这是我对 F# 翻译的(糟糕的)尝试:
let function1_grad(x : float [], func : float, grad : float [], obj_ : obj) =
func <- 100.*System.Math.Pow(x.[0]+3.,4.) + System.Math.Pow(x.[1]-3., 4.)
grad.[0] <- 400.*System.Math.Pow(x.[0]+3,3.);
grad.[1] <- 4.*System.Math.Pow(x.[1]-3.,3.);
let runOptim() =
let x = [|0.; 0.|]
let epsg = 0.0000000001
let epsf = 0.
let epsx = 0.
let stpmax = 0.1
let maxits = 0
let state = alglib.minlbfgsstate
let mutable rep = alglib.minlbfgsreport()
// first run
alglib.minlbfgscreate(1, x, state)
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits)
alglib.minlbfgssetstpmax(state, stpmax)
alglib.minlbfgsoptimize(state, function1_grad, null, null)
alglib.minlbfgsresults(state, x, rep)
printfn "{0}", alglib.ap.format(x,2)
let x = [|10.; 10.|]
alglib.minlbfgsrestartfrom(state, x)
alglib.minlbfgsoptimize(state, function1_grad, null, null)
alglib.minlbfgsresults(state, x, rep)
printfn "%A" rep.terminationtype
printfn "%A" (alglib.ap.format(x, 2))
System.Console.ReadLine() |> ignore
该库使用了很多byref
和out
参数,因此将其转换为F#并不简单,您需要妥善处理它们:
#r @"C:\packages\alglibnet2\lib\alglibnet2.dll"
open System
let function1_grad(x : float [], func : float byref, grad : float [], obj_ : obj) =
func <- 100.*System.Math.Pow(x.[0]+3.,4.) + System.Math.Pow(x.[1]-3., 4.)
grad.[0] <- 400.*System.Math.Pow(x.[0]+3. ,3.)
grad.[1] <- 4.*System.Math.Pow(x.[1]-3. ,3.)
let runOptim() =
let x = ref [|0.; 0.|]
let epsg = 0.0000000001
let epsf = 0.
let epsx = 0.
let stpmax = 0.1
let maxits = 0
let state = alglib.minlbfgscreate(1, !x)
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits)
alglib.minlbfgssetstpmax(state, stpmax)
alglib.minlbfgsoptimize(state, (fun a b c d -> function1_grad(a, &b, c, d)), null, null)
let rep = alglib.minlbfgsresults(state, x)
printfn "%s" (alglib.ap.format(!x, 2))
let x = ref [|10.; 10.|]
alglib.minlbfgsrestartfrom(state, !x)
alglib.minlbfgsoptimize(state, (fun a b c d -> function1_grad(a, &b, c, d)), null, null)
alglib.minlbfgsresults(state, x, ref rep)
printfn "%i" rep.terminationtype
printfn "%s" (alglib.ap.format(!x, 2))
System.Console.ReadLine() |> ignore
我建议您阅读一些有关 F# 如何处理 out
和 byref
参数的内容,例如不要在声明中将 ref
与 byref
混淆,并且请记住,out
参数可被视为 F# 的附加元组结果。
但我认为最棘手的部分是转换为带有 byref 参数的委托,您可以在 this answer.
中阅读相关内容
请注意,您可以使用 **
运算符代替 Math.Pow
:
func <- 100. * (x.[0]+3. ** 4.) + (x.[1]-3. ** 4.)
grad.[0] <- 400. * (x.[0]+3. ** 3.)
grad.[1] <- 4. * (x.[1]-3. ** 3.)
有人可以帮助将以下 C# 示例代码从 Alglib 库翻译成 F# 吗?我无法在 Internet 上找到有关如何从 F# 使用它的任何示例。
public static void function1_grad(double[] x, ref double func, double[] grad, object obj)
{
// this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
// and its derivatives df/d0 and df/dx1
func = 100*System.Math.Pow(x[0]+3,4) + System.Math.Pow(x[1]-3,4);
grad[0] = 400*System.Math.Pow(x[0]+3,3);
grad[1] = 4*System.Math.Pow(x[1]-3,3);
}
public static int Main(string[] args)
{
//
// This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
// using LBFGS method.
//
// Several advanced techniques are demonstrated:
// * upper limit on step size
// * restart from new point
//
double[] x = new double[]{0,0};
double epsg = 0.0000000001;
double epsf = 0;
double epsx = 0;
double stpmax = 0.1;
int maxits = 0;
alglib.minlbfgsstate state;
alglib.minlbfgsreport rep;
// first run
alglib.minlbfgscreate(1, x, out state);
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits);
alglib.minlbfgssetstpmax(state, stpmax);
alglib.minlbfgsoptimize(state, function1_grad, null, null);
alglib.minlbfgsresults(state, out x, out rep);
System.Console.WriteLine("{0}", alglib.ap.format(x,2)); // EXPECTED: [-3,3]
// second run - algorithm is restarted
x = new double[]{10,10};
alglib.minlbfgsrestartfrom(state, x);
alglib.minlbfgsoptimize(state, function1_grad, null, null);
alglib.minlbfgsresults(state, out x, out rep);
System.Console.WriteLine("{0}", rep.terminationtype); // EXPECTED: 4
System.Console.WriteLine("{0}", alglib.ap.format(x,2)); // EXPECTED: [-3,3]
System.Console.ReadLine();
return 0;
}
这是我对 F# 翻译的(糟糕的)尝试:
let function1_grad(x : float [], func : float, grad : float [], obj_ : obj) =
func <- 100.*System.Math.Pow(x.[0]+3.,4.) + System.Math.Pow(x.[1]-3., 4.)
grad.[0] <- 400.*System.Math.Pow(x.[0]+3,3.);
grad.[1] <- 4.*System.Math.Pow(x.[1]-3.,3.);
let runOptim() =
let x = [|0.; 0.|]
let epsg = 0.0000000001
let epsf = 0.
let epsx = 0.
let stpmax = 0.1
let maxits = 0
let state = alglib.minlbfgsstate
let mutable rep = alglib.minlbfgsreport()
// first run
alglib.minlbfgscreate(1, x, state)
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits)
alglib.minlbfgssetstpmax(state, stpmax)
alglib.minlbfgsoptimize(state, function1_grad, null, null)
alglib.minlbfgsresults(state, x, rep)
printfn "{0}", alglib.ap.format(x,2)
let x = [|10.; 10.|]
alglib.minlbfgsrestartfrom(state, x)
alglib.minlbfgsoptimize(state, function1_grad, null, null)
alglib.minlbfgsresults(state, x, rep)
printfn "%A" rep.terminationtype
printfn "%A" (alglib.ap.format(x, 2))
System.Console.ReadLine() |> ignore
该库使用了很多byref
和out
参数,因此将其转换为F#并不简单,您需要妥善处理它们:
#r @"C:\packages\alglibnet2\lib\alglibnet2.dll"
open System
let function1_grad(x : float [], func : float byref, grad : float [], obj_ : obj) =
func <- 100.*System.Math.Pow(x.[0]+3.,4.) + System.Math.Pow(x.[1]-3., 4.)
grad.[0] <- 400.*System.Math.Pow(x.[0]+3. ,3.)
grad.[1] <- 4.*System.Math.Pow(x.[1]-3. ,3.)
let runOptim() =
let x = ref [|0.; 0.|]
let epsg = 0.0000000001
let epsf = 0.
let epsx = 0.
let stpmax = 0.1
let maxits = 0
let state = alglib.minlbfgscreate(1, !x)
alglib.minlbfgssetcond(state, epsg, epsf, epsx, maxits)
alglib.minlbfgssetstpmax(state, stpmax)
alglib.minlbfgsoptimize(state, (fun a b c d -> function1_grad(a, &b, c, d)), null, null)
let rep = alglib.minlbfgsresults(state, x)
printfn "%s" (alglib.ap.format(!x, 2))
let x = ref [|10.; 10.|]
alglib.minlbfgsrestartfrom(state, !x)
alglib.minlbfgsoptimize(state, (fun a b c d -> function1_grad(a, &b, c, d)), null, null)
alglib.minlbfgsresults(state, x, ref rep)
printfn "%i" rep.terminationtype
printfn "%s" (alglib.ap.format(!x, 2))
System.Console.ReadLine() |> ignore
我建议您阅读一些有关 F# 如何处理 out
和 byref
参数的内容,例如不要在声明中将 ref
与 byref
混淆,并且请记住,out
参数可被视为 F# 的附加元组结果。
但我认为最棘手的部分是转换为带有 byref 参数的委托,您可以在 this answer.
中阅读相关内容请注意,您可以使用 **
运算符代替 Math.Pow
:
func <- 100. * (x.[0]+3. ** 4.) + (x.[1]-3. ** 4.)
grad.[0] <- 400. * (x.[0]+3. ** 3.)
grad.[1] <- 4. * (x.[1]-3. ** 3.)