【发布时间】:2010-09-08 19:53:38
【问题描述】:
我在让自动区分在 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() 。
抱歉,如果这完全模糊或无法理解。如果不清楚,我会在 cmets 中回答任何问题。
我希望有一个解决方案!提前致谢,
阿什利
【问题讨论】:
-
我不确定我是否明白你在这里问什么。如果我正确阅读了您的问题,您似乎希望能够在使用示例函数
f时使用您的Price方法(未修改)。但是f使用您的自定义运算符,而对双精度进行操作的 C# 方法将始终使用double运算符。 -
请注意,如果您只对导数的数值感兴趣而没有符号项,只需使用近似公式:
f'(x) = (f(x+h)-f(x))/h用于一些小的h -
@dtb 是的,你完全正确。理想情况下,我想对函数参数使用转换/强制,以将它们从 double 转换为 Diff。
-
@Dario 是的,我只对数值导数感兴趣。然而,使用近似有两个问题。 1)它非常不准确(价格),2)h 需要从一个函数变为另一个函数并使用变量 x 来优化该方法,因此我更喜欢一个更通用的。
-
与
maturity=5、frequency=10、coupon=11和nominal=13我得到Price(Id(2))==71.493、Differentiate(Price(Id(2)))==-423.782和Differentiate(Differentiate(Price(Id(2))))==5039.610。对吗?
标签: c# f# automatic-differentiation