我刚刚下载了ILNumerics的最后一个版本,用于我的F#项目。在F#中可以利用这个库吗?我尝试过简单的计算,这看起来非常麻烦(在F#中)。
我想建立一个有约束的(甚至是无约束的)优化问题。通常的Rosenbrock函数可以完成,然后我将使用自己的函数。我在定义数组的过程中遇到了困难。我所能定义的唯一一种数组是一个RetArray,例如,使用以下代码
let vector = ILMath.vector<float>(1.0, 2.0)编译器表示向量是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;;我得到了
错误:对象引用未设置为对象的实例。
建议在ILNumerics中使用F#的方法是什么?是否可以在F#中本地使用库,或者我被迫从C#库调用F#代码来使用整个ILNumerics库?除了引用的问题之外,我在理解ILNumerics的基本逻辑(在F#中移植时)方面也有问题。
例如,使用范围的F#等效于C#,如示例代码所示,如下所示:
using (ILScope.Enter(inData)) { ...
}发布于 2021-03-10 05:15:49
c的第二次访问失败的原因是,ILNumerics正在执行一些非常不寻常的内存管理,在您可能没有预料到的情况下,这种管理会自动进行释放向量的内存。在C#中,这是通过从vector到Array的隐式转换来管理的。
// C#
var A = vector<int>(1, 2, 3); // bad!
Array<int> A = vector<int>(1, 2, 3); // goodF#没有隐式类型转换,但是可以手动调用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请注意,我已经创建了一个名为!的内联助手函数,以使这更容易。每次在ILNumerics中创建F#向量时,都必须调用此函数将其转换为数组。(我知道,这很难看,但我看不出有什么更容易的选择。)
要回答最后一个问题,等效的F#代码是:
use _scope = Scope.Enter(inData)
...发布于 2021-03-10 07:04:32
就布里安伯恩斯的回答来说,有几件事你可以做,这样才能让自己更容易。
我个人不会选择定义自定义操作符的路线--尤其是覆盖现有的。相反,也许您应该考虑使用计算表达式来处理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! (desugar to Bind)和return (desugars to Return,duh)关键字。
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类型是从这里开始的方法。
https://stackoverflow.com/questions/66556098
复制相似问题