F# 和 ILNumerics
F# and ILNumerics
我刚刚下载了最新版本的 ILNumerics,用于我的 F# 项目。是否可以在 F# 中利用这个库?我已经尝试过简单的计算,但它似乎非常麻烦(在 F# 中)。
我想设置一个有约束(甚至无约束)的优化问题。通常的 Rosenbrock 函数就可以了,然后我将使用我自己的函数。我什至很难定义一个数组。我可以定义的唯一一种数组是 RetArray,例如使用此代码
let vector = ILMath.vector<float>(1.0, 2.0)
编译器表示 vector 是一个 RetArray;我认为这是因为它是从函数返回的(即:ILMath.vector)。如果我定义另一个类似的向量,我可以 - 例如 - 对向量求和,只需编写,例如
let a = ILMath.vector<float>(1.0, 2.0)
let b = ILMath.vector<float>(3.2,2.2)
let c = a + b
然后我得到
RetArray<float> = seq [4.2; 4.2]
但是如果我再次尝试检索 c 的值,例如在 FSI 中写入,
c;;
我明白了
Error: Object reference not set to an instance of an object.
在 F# 中使用 ILNumerics 的建议方法是什么?是否可以在 F# 中本地使用该库,或者我被迫从 C# 库调用我的 F# 代码以使用整个 ILNumerics 库?除了引用的问题,我在理解 ILNumerics 的基本逻辑时遇到了问题,当移植到 F# 中时。
例如,在示例代码中使用作用域的 C# 的 F# 等价物是什么,如:
using (ILScope.Enter(inData)) { ...
}
第二次访问 c
失败的原因是 ILNumerics 正在进行一些非常不寻常的内存管理,它会在您意想不到的时候自动 releases the vector's memory。在 C# 中,这是通过从 vector
到 Array
:
的隐式转换来管理的
// C#
var A = vector<int>(1, 2, 3); // bad!
Array<int> A = vector<int>(1, 2, 3); // good
F# 没有隐式类型转换,但您可以手动调用 op_Implicit
成员,如下所示:
open ILNumerics
open type ILMath // open static class - new feature in F# 5
let inline (!) (x : RetArray<'t>) =
Array<'t>.op_Implicit(x)
[<EntryPoint>]
let main argv =
let a = !vector<float>(1.0, 2.0)
let b = !vector<float>(3.2,2.2)
let c = !(a + b)
printfn "%A" c
printfn "%A" c
0
请注意,我创建了一个名为 !
的内联辅助函数,以简化此过程。每次在 F# 中创建 ILNumerics 向量时,都必须调用此函数将其转换为数组。 (这很丑,我知道,但我没有看到更简单的选择。)
要回答您的最后一个问题,等效的 F# 代码是:
use _scope = Scope.Enter(inData)
...
为了详细说明 brianberns 的回答,您可以做几件事来让自己更轻松。
我个人不会走定义自定义运算符的路线 - 尤其是 overrides an existing one. Instead, perhaps you should consider using a computation expression 用于 ILMath 类型的运算符。这将允许您隐藏很多丑陋之处,这些丑陋之处在使用非 F# 标准(例如隐式类型转换)的库工作时会出现。
我无权访问 ILMath,因此我刚刚实现了这些虚拟替代方案,以便让我的代码能够编译。我怀疑您应该能够不复制它,其余代码将按预期工作
module ILMath =
type RetArray<'t> = { Values: 't seq }
and Array<'t> = { OtherValues: 't seq } with
static member op_Implicit(x: RetArray<_>) = { OtherValues = x.Values }
static member inline (+) (x1, x2) = { Values = (x1.OtherValues, x2.OtherValues) ||> Seq.map2 (+) }
type ILMath =
static member vector<'t>([<ParamArray>] vs : 't []) = { ILMath.Values = vs }
如果您以前从未见过或实现过计算表达式,您应该查看我引用的文档。基本上,它以您决定的方式在一些丑陋的东西之上添加了一些漂亮的语法糖。我的示例实现仅添加 let!
(脱糖到 Bind
)和 return
(脱糖到 Return
,呃)关键字。
type ILMathBuilder() =
member __.Bind(x: ILMath.RetArray<'t>, f) =
f(ILMath.Array<'t>.op_Implicit(x))
member __.Return(x: ILMath.RetArray<'t>) =
ILMath.Array<'t>.op_Implicit(x)
let ilmath = ILMathBuilder()
这应该在顶层定义和实例化(ilmath
变量)。这允许你写
let c = ilmath {
let! a = vector(1.0, 2.0)
let! b = vector(3.2, 2.2)
return a + b
}
当然,此实现仅添加了对极少数内容的支持,并且要求始终返回 RetArray<'t>
类型的值。根据文档扩展 ILMathBuilder
类型是从这里开始的方法。
我刚刚下载了最新版本的 ILNumerics,用于我的 F# 项目。是否可以在 F# 中利用这个库?我已经尝试过简单的计算,但它似乎非常麻烦(在 F# 中)。
我想设置一个有约束(甚至无约束)的优化问题。通常的 Rosenbrock 函数就可以了,然后我将使用我自己的函数。我什至很难定义一个数组。我可以定义的唯一一种数组是 RetArray,例如使用此代码
let vector = ILMath.vector<float>(1.0, 2.0)
编译器表示 vector 是一个 RetArray;我认为这是因为它是从函数返回的(即:ILMath.vector)。如果我定义另一个类似的向量,我可以 - 例如 - 对向量求和,只需编写,例如
let a = ILMath.vector<float>(1.0, 2.0)
let b = ILMath.vector<float>(3.2,2.2)
let c = a + b
然后我得到
RetArray<float> = seq [4.2; 4.2]
但是如果我再次尝试检索 c 的值,例如在 FSI 中写入,
c;;
我明白了
Error: Object reference not set to an instance of an object.
在 F# 中使用 ILNumerics 的建议方法是什么?是否可以在 F# 中本地使用该库,或者我被迫从 C# 库调用我的 F# 代码以使用整个 ILNumerics 库?除了引用的问题,我在理解 ILNumerics 的基本逻辑时遇到了问题,当移植到 F# 中时。
例如,在示例代码中使用作用域的 C# 的 F# 等价物是什么,如:
using (ILScope.Enter(inData)) { ...
}
第二次访问 c
失败的原因是 ILNumerics 正在进行一些非常不寻常的内存管理,它会在您意想不到的时候自动 releases the vector's memory。在 C# 中,这是通过从 vector
到 Array
:
// C#
var A = vector<int>(1, 2, 3); // bad!
Array<int> A = vector<int>(1, 2, 3); // good
F# 没有隐式类型转换,但您可以手动调用 op_Implicit
成员,如下所示:
open ILNumerics
open type ILMath // open static class - new feature in F# 5
let inline (!) (x : RetArray<'t>) =
Array<'t>.op_Implicit(x)
[<EntryPoint>]
let main argv =
let a = !vector<float>(1.0, 2.0)
let b = !vector<float>(3.2,2.2)
let c = !(a + b)
printfn "%A" c
printfn "%A" c
0
请注意,我创建了一个名为 !
的内联辅助函数,以简化此过程。每次在 F# 中创建 ILNumerics 向量时,都必须调用此函数将其转换为数组。 (这很丑,我知道,但我没有看到更简单的选择。)
要回答您的最后一个问题,等效的 F# 代码是:
use _scope = Scope.Enter(inData)
...
为了详细说明 brianberns 的回答,您可以做几件事来让自己更轻松。
我个人不会走定义自定义运算符的路线 - 尤其是 overrides an existing one. Instead, perhaps you should consider using a computation expression 用于 ILMath 类型的运算符。这将允许您隐藏很多丑陋之处,这些丑陋之处在使用非 F# 标准(例如隐式类型转换)的库工作时会出现。
我无权访问 ILMath,因此我刚刚实现了这些虚拟替代方案,以便让我的代码能够编译。我怀疑您应该能够不复制它,其余代码将按预期工作
module ILMath =
type RetArray<'t> = { Values: 't seq }
and Array<'t> = { OtherValues: 't seq } with
static member op_Implicit(x: RetArray<_>) = { OtherValues = x.Values }
static member inline (+) (x1, x2) = { Values = (x1.OtherValues, x2.OtherValues) ||> Seq.map2 (+) }
type ILMath =
static member vector<'t>([<ParamArray>] vs : 't []) = { ILMath.Values = vs }
如果您以前从未见过或实现过计算表达式,您应该查看我引用的文档。基本上,它以您决定的方式在一些丑陋的东西之上添加了一些漂亮的语法糖。我的示例实现仅添加 let!
(脱糖到 Bind
)和 return
(脱糖到 Return
,呃)关键字。
type ILMathBuilder() =
member __.Bind(x: ILMath.RetArray<'t>, f) =
f(ILMath.Array<'t>.op_Implicit(x))
member __.Return(x: ILMath.RetArray<'t>) =
ILMath.Array<'t>.op_Implicit(x)
let ilmath = ILMathBuilder()
这应该在顶层定义和实例化(ilmath
变量)。这允许你写
let c = ilmath {
let! a = vector(1.0, 2.0)
let! b = vector(3.2, 2.2)
return a + b
}
当然,此实现仅添加了对极少数内容的支持,并且要求始终返回 RetArray<'t>
类型的值。根据文档扩展 ILMathBuilder
类型是从这里开始的方法。