Frage

ich habe ein Problem bekommen Automatische Differenzierung zur Arbeit zwischen C # und F #.

In C # ich eine Funktion haben, die eine doppelte nimmt und eine doppelte, sagen:

private double Price(double yield)
{
    double price;

    price = 0;

    for (int index = 1; index <= _maturity * _frequency; index++)
    {
        price += (_coupon / _frequency) * _nominal / Math.Pow(1 + (yield / _frequency), index);
    }

    price += _nominal / Math.Pow(1 + (yield / _frequency), _maturity * _frequency);

    return price;
}

nahm ich diese Funktion gezielt, da die Math.pow sehr unerschwinglich ist, und erlaubt nur eine doppelte oder des int der für seine Parameter.

Ich möchte diese Funktion Automatische Differenzierung unterscheiden. Ich habe die Methode für diese in F # geschrieben:

type Diff(d : double, df : Lazy<Diff>) = class
    member x.d = d
    member x.df = df
    static member (+) (x : Diff, y : Diff) = 
        Diff(x.d + y.d, lazy (x.df.Value + y.df.Value)) 
    static member (-) (x : Diff, y : Diff) = 
        Diff(x.d - y.d, lazy (x.df.Value - y.df.Value))
    static member (*) (x : Diff, a : double) = 
        Diff(x.d * a, lazy (x.df.Value * a))
    static member (*) (x : Diff, y : Diff) = 
        Diff(x.d * y.d, lazy ((x.df.Value * y) + (y.df.Value * x)))
    override x.ToString() =
        x.d.ToString()
end

let rec dZero = Diff(0.0, lazy dZero)

let dConst x = Diff(x, lazy dZero)

let dId x = Diff(x, lazy dConst 1.0)

let Differentiate (x:Diff) = x.df.Value

// Example function
let f (x:Diff) = x*x*x;

// Example usage:
// (f (dId 5)).ToString = "125"
// (Differentiate (f (dId 5))).ToString = "75"
// (Differentiate (Differentate (f (dId 5)))).ToString = "30"

Leider, ich brauche eine Art Diff in meinen Preis zu ernähren (..) Funktion einen Typ Diff zu erzeugen, die dann in meine Differente (..) Funktion zugeführt wird einen anderen Typ Diff zurückzukehren.

Mein C # Funktion jedoch funktioniert nur auf verdoppelt (und ich mag es so bleiben, wie es in anderen Orten in meinem C # Programm verwendet wird).

Der einzige Weg, ich denke, kann dies zu lösen, ist jede Funktion zweimal zu schreiben, die als offensichtlich schrecklich ist:

1) Ich kann auch schreiben Sie einfach eine differenzierte Version jedes Mal 2) Das ist kein sehr erweiterbares Modell

So ist es eine Möglichkeit, dies zu umgehen, oder vielleicht meine Doppelfunktionen in Diff Funktionen wandeln (vorzugsweise in F #). Im Idealfall wäre, wie ich gerade eine (Doppel -> double) zu werfen. In Funktion und eine Diff.ToString () raus

Sorry, wenn dies völlig vage oder gar nicht zu verstehen. Ich werde keine Fragen in den Kommentaren beantworten, wenn dies ist unklar.

Ich hoffe, es gibt eine Lösung für dieses! Vielen Dank im Voraus,

Ashley

War es hilfreich?

Lösung

Sie können Haskell Typklassen neu erfinden:

interface Eq<T>
{
    bool Equal(T a, T b);
    bool NotEqual(T a, T b);
}

interface Num<T> : Eq<T>
{
    T Zero { get; }
    T Add(T a, T b);
    T Subtract(T a, T b);
    T Multiply(T a, T b);
    T Negate(T a);
}

sealed class Int : Num<int>
{
    public static readonly Int Instance = new Int();
    private Int() { }
    public bool Equal(int a, int b) { return a == b; }
    public bool NotEqual(int a, int b) { return a != b; }
    public int Zero { get { return 0; } }
    public int Add(int a, int b) { return a + b; }
    public int Subtract(int a, int b) { return a - b; }
    public int Multiply(int a, int b) { return a * b; }
    public int Negate(int a) { return -a; }
}

Dann können Sie tun:

static T F<M, T>(M m, T x) where M : Num<T>
{
    return m.Multiply(x, m.Multiply(x, x));
}

static void Main(string[] args)
{
    Console.WriteLine(F(Int.Instance, 5));  // prints "125"
}

Und dann mit:

class Diff
{
    public readonly double d;
    public readonly Lazy<Diff> df;

    public Diff(double d, Lazy<Diff> df)
    {
        this.d = d;
        this.df = df;
    }
}

class DiffClass : Floating<Diff>
{
    public static readonly DiffClass Instance = new DiffClass();
    private static readonly Diff zero = new Diff(0.0, new Lazy<Diff>(() => DiffClass.zero));
    private DiffClass() { }
    public Diff Zero { get { return zero; } }
    public Diff Add(Diff a, Diff b) { return new Diff(a.d + b.d, new Lazy<Diff>(() => Add(a.df.Value, b.df.Value))); }
    public Diff Subtract(Diff a, Diff b) { return new Diff(a.d - b.d, new Lazy<Diff>(() => Subtract(a.df.Value, b.df.Value))); }
    public Diff Multiply(Diff a, Diff b) { return new Diff(a.d * b.d, new Lazy<Diff>(() => Add(Multiply(a.df.Value, b), Multiply(b.df.Value, a)))); }
    ...
}

Sie können dies tun:

static T Price<M, T>(M m, T _maturity, T _frequency, T _coupon, T _nominal, T yield) where M : Floating<T>
{
    T price;

    price = m.Zero;

    for (T index = m.Succ(m.Zero); m.Compare(index, m.Multiply(_maturity, _frequency)) <= 0; index = m.Succ(index))
    {
        price = m.Add(price, m.Divide(m.Multiply(m.Divide(_coupon, _frequency), _nominal), m.Power(m.Add(m.Succ(m.Zero), m.Divide(yield, _frequency)), index)));
    }

    price = m.Add(price, m.Divide(_nominal, m.Power(m.Add(m.Succ(m.Zero), m.Divide(yield, _frequency)), m.Multiply(_maturity, _frequency))));

    return price;
}

Aber das ist nicht wirklich hübsch.

In der Tat, es liest sich fast wie Code, der eine LINQ Expression-Baum erstellt. Vielleicht können Sie Quellcode Expression Baum Transformation anstelle von Überladen von Operatoren erreichen Automatische Differenzierung

Andere Tipps

Es gibt keinen Weg, um Ihre vorhandenen C # Funktion zu nutzen, noch gibt es eine einfache Möglichkeit, es zu einer Funktion zu heben, die auf Mitglieder der Typ Diff arbeiten könnte. Sobald die Funktion kompiliert worden ist, ist es undurchsichtig und die innere Struktur ist unavaliable; alles, was Sie tun können, ist die Funktion mit einem doppelten Argument aufrufen und ein Doppel Ergebnis. Darüber hinaus Ihre Price Methode verwendet Operationen, die Sie nicht einmal auf Ihrer Diff Klasse definiert haben sowieso ((\) und Pow).

Ich bin mir nicht sicher, ob es für Ihre Zwecke akzeptabel wäre, aber eine mögliche Alternative wäre, eine generische Inline-Version Ihrer Price Funktion in F # zu schreiben, die dann entweder auf Doppel oder Diffs arbeiten könnten (vorausgesetzt, dass Sie hinzufügen die (\) und Pow Operatoren).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top