我在让自动微分在 C# 和 F# 之间工作时遇到问题。
在 C# 中,我有一个接受双精度并返回双精度的函数,例如:
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;
}
我专门选择了这个函数,因为 Math.pow 非常禁止,并且只允许使用 double 或 int 作为其参数。
我想使用自动微分来区分这个功能。我在 F# 中为此编写了方法:
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"
不幸的是,我需要将类型 Diff 输入到我的 Price(..) 函数中以生成类型 Diff,然后将其输入到我的 Differente(..) 函数中以返回另一种类型 Diff。
然而,我的 C# 函数仅适用于双打(我希望它保持这种状态,因为它在我的 C# 程序的其他地方使用)。
我能想到解决这个问题的唯一方法是将每个函数编写两次,这显然很糟糕:
1)我还不如每次都写一个差异化的版本 2)这不是一个非常可扩展的模型
那么有什么办法可以解决这个问题,或者可能将我的双重函数强制转换为 Diff 函数(最好在 F# 中)。理想情况下,我只想抛出一个 (double -> double) 函数并得到一个 Diff.ToString() 。
抱歉,如果这完全模糊或无法理解。如果不清楚,我将在评论中回答任何问题。
我希望有一个解决方案!提前致谢,
阿什利