0

F# では、一般的な数学ステップ関数をどのように記述しますか?

(Oliver) Heaviside ステップ関数は、x が負の場合は 0 を返し、そうでない場合は 1 を返す関数です。

これまでの私の試みの要約は次のとおりです。

// attempt 1:
let inline stepFct1< ^T when ^T : (static member op_GreaterThan: ^T * float -> bool) 
    >     (x:^T) : ^T = 
    //if (^T : (static member op_GreaterThan) (x 0.0) ) then x  //ouch fails also
    if  (>) x 0.0 then x
    else 0.0

コンパイラのメッセージ: エラー FS0001: 型パラメーターに制約がありません 'when ^T : comparison'

// attempt 2:
let inline stepFct2<^T when ^T : (static member (>): ^T * ^T -> bool) > (x:^T) : ^T = 
    match x with 
    | x when x > 0.0 -> 1.0
    | 0.0

FSC は次のように述べています: エラー FS0010: パターンに予期しない中置演算子があります

動機:

Ian の Cumulative-Normal 関数と Black-Scholes 関数をここで書き換えて、自動微分 (DiffSharp) を使用しようとしています。Ian の Cumulative Normal は float で動作します。AutoDiff.DualG を含む任意の数値型で動作する汎用バージョンが欲しいです。累積正規関数に「より大きい」ステートメントが含まれています。

編集:グスタボ、ありがとう、私はあなたの答えを受け入れました-単純なステップ関数がコンパイルされるようになりました。

しかし、累積法線のケースでは役に立たないようです。このコードを考えると:

// Cumulative Normal Distribution Function - attempt to write a generic version
let inline CDF(x:^T) : ^T = 
    let (b1,b2,b3)  = (0.319381530, -0.356563782, 1.781477937)
    let (b4,b5)     = (-1.821255978, 1.330274429)
    let (p , c )    = (0.2316419  ,  0.39894228)
    let (zero, one) = (LanguagePrimitives.GenericZero, LanguagePrimitives.GenericOne)
    if x > zero then
        let t = one / (one + p * x) 
        (one - c * exp( -x * x / 2.0)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1)) 
    else
        let t = 1.0 / (one - p * x) 
        (c * exp( -x * x / 2.0)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))

FSI は次のように述べています。

C:\stdin(116,32): warning FS0064: This construct causes code to be less generic 
than indicated by the type annotations. 
The type variable 'T has been constrained to be type 'float'.

val inline CDF : x:float -> float
> CDF 0.1M;;
CDF 0.1M;;
----^^^^
C:\stdin(122,5): error FS0001: This expression was expected to have type
    float
but here has type
    decimal
>

CDFをジェネリックにする方法を知っている人はいますか?

4

1 に答える 1

5

LanguagePrimitives.GenericZero/を使用GenericOneして、残りは型推論に任せます

// attempt 1:
let inline stepFct1 x =
    let zero = LanguagePrimitives.GenericZero 
    if x > zero then x
    else zero

あなたが実装したい機能と一緒にあなたが送ったリンクを見ました。FSharpPlus (F#+)は、専用のGeneric Numbers モジュールが含まれているため、汎用数学コードの記述に役立つ場合があります。または、少なくともそこからいくつかのテクニックを取得できます。

アップデート

複雑さをより高いレベルに引き上げる更新された質問については、F#+プロジェクトの最新バージョンを使用したソリューションを次に示します。

let inline CDF(x:^T) : ^T = 
    let num x = fromRational (x </ratio/> 1000000000I)
    let (b1,b2,b3)  = (num 319381530I   , num -356563782I  , num 1781477937I)
    let (b4,b5)     = (num -1821255978I , num 1330274429I)
    let (p , c )    = (num  0231641900I , num 0398942280I)
    let (zero, one, two) = 0G, 1G, 2G
    if x > zero then
        let t = one / (one + p * x) 
        (one - c * exp( -x * x / two)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1)) 
    else
        let t = one / (one - p * x) 
        (c * exp( -x * x / two)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))

残念ながら、現時点では、一部の関数がライブラリ内で内部としてマークされているため、公開されていないことに気付きましたが、ここで実際の例でそれらを再作成して、関数をテストできるようにfloatしましたfloat32

今年の終わりまでに新しいバージョンがリリースされる予定ですが、それまでの間は、分岐したり、内部を削除してコンパイルしたり、リンクされた例で行ったように関数を再作成したりできます。

Generic Maths に興味がある場合は、お気軽にコードやユース ケースを提供してください。

于 2014-11-27T22:06:16.607 に答える