首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F#和ILNumerics

F#和ILNumerics
EN

Stack Overflow用户
提问于 2021-03-09 23:12:59
回答 2查看 94关注 0票数 2

我刚刚下载了ILNumerics的最后一个版本,用于我的F#项目。在F#中可以利用这个库吗?我尝试过简单的计算,这看起来非常麻烦(在F#中)。

我想建立一个有约束的(甚至是无约束的)优化问题。通常的Rosenbrock函数可以完成,然后我将使用自己的函数。我在定义数组的过程中遇到了困难。我所能定义的唯一一种数组是一个RetArray,例如,使用以下代码

代码语言:javascript
复制
let vector = ILMath.vector<float>(1.0, 2.0)

编译器表示向量是RetArray;我认为这是因为它是从函数(即: ILMath.vector)返回的。如果我定义另一个类似的向量,我可以-例如-和向量,简单地写,例如

代码语言:javascript
复制
let a = ILMath.vector<float>(1.0, 2.0)
let b = ILMath.vector<float>(3.2,2.2)
let c = a  + b 

我得到了

代码语言:javascript
复制
RetArray<float> = seq [4.2; 4.2]

但是,如果我试图检索c的值,再次编写,例如在FSI中,

代码语言:javascript
复制
c;;

我得到了

错误:对象引用未设置为对象的实例。

建议在ILNumerics中使用F#的方法是什么?是否可以在F#中本地使用库,或者我被迫从C#库调用F#代码来使用整个ILNumerics库?除了引用的问题之外,我在理解ILNumerics的基本逻辑(在F#中移植时)方面也有问题。

例如,使用范围的F#等效于C#,如示例代码所示,如下所示:

代码语言:javascript
复制
using (ILScope.Enter(inData)) { ...

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-10 05:15:49

c的第二次访问失败的原因是,ILNumerics正在执行一些非常不寻常的内存管理,在您可能没有预料到的情况下,这种管理会自动进行释放向量的内存。在C#中,这是通过从vectorArray的隐式转换来管理的。

代码语言:javascript
复制
// C#
var A = vector<int>(1, 2, 3);          // bad!
Array<int> A = vector<int>(1, 2, 3);   // good

F#没有隐式类型转换,但是可以手动调用op_Implicit成员,如下所示:

代码语言:javascript
复制
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#代码是:

代码语言:javascript
复制
use _scope = Scope.Enter(inData)
...
票数 4
EN

Stack Overflow用户

发布于 2021-03-10 07:04:32

就布里安伯恩斯的回答来说,有几件事你可以做,这样才能让自己更容易。

我个人不会选择定义自定义操作符的路线--尤其是覆盖现有的。相反,也许您应该考虑使用计算表达式来处理ILMath类型。这将允许您隐藏大量的丑陋,这是在使用非F#标准(例如,隐式类型转换)的库时出现的。

我没有访问ILMath的权限,所以我刚刚实现了这些虚拟的替代方案,以使我的代码能够编译。我怀疑您应该能够不将其复制到其中,其余代码将按预期工作。

代码语言:javascript
复制
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)关键字。

代码语言:javascript
复制
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变量)。这让你可以写

代码语言:javascript
复制
let c = ilmath {
    let! a = vector(1.0, 2.0)
    let! b = vector(3.2, 2.2)
    return a + b
}

当然,这个实现只增加了对很少东西的支持,并且要求,例如,总是返回一个类型为RetArray<'t>的值。根据文档扩展ILMathBuilder类型是从这里开始的方法。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66556098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档