2017-01-22 3 views
0

Quelqu'un peut-il aider à traduire le code d'exemple C# suivant de la bibliothèque Alglib en F #? Je n'ai pas pu trouver d'exemple sur Internet pour savoir comment l'utiliser à partir de F #.Gestion des paramètres byref et out lors de la traduction de C# en 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; 
} 

Et voici mon (pauvre) tentative de traduction 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 
+1

Qu'aimez-vous pas votre traduction? Quelle est ta question? Quel est votre problème? –

+1

@FyodorSoikin Je ne sais pas ce que sont les arguments "ref double func", "object obj" et comment les traduire. Des tonnes d'erreurs résultantes dans ma tentative. –

+1

Que diriez-vous de décrire des problèmes spécifiques dans votre question? Vous avez beaucoup plus de chances d'obtenir une réponse utile si vous décrivez vos problèmes de façon précise et minime que si vous publiez simplement un gros morceau de code et attendez que les gens l'examinent. –

Répondre

3

Cette bibliothèque utilise beaucoup de byref et out paramètres, il est donc pas facile de traduire en F #, vous avez besoin pour les traiter correctement:

#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 

Je vous recommande de lire un peu sur la façon dont gère F # out et byref paramètres, par exemple, ne confondez pas ref avec byref dans la déclaration et gardez à l'esprit que les paramètres out peuvent être considérés comme des résultats supplémentaires pour F #.

Mais je pense que la partie la plus difficile est la conversion en un délégué avec un paramètre byref, vous pouvez lire à ce sujet dans this answer.

Notez que vous pouvez utiliser l'opérateur ** au lieu de 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.) 
+1

Merci Gustavo. Je pense que votre réponse sera d'une grande aide pour les personnes non-C# qui cherchent à faire de l'optimisation dans F # à l'avenir. –

+2

De rien. Ensuite, je vous suggère d'éditer le titre et de mettre quelque chose en rapport avec les paramètres byref et out, de cette façon il est plus facile pour eux de trouver cette réponse. – Gustavo