Перезапись C# кодирует в F#

Подвижный: многострочное сообщение о фиксации на командной строке?

Хит входят.

$ hg commit -m "Did some work
> Now I'm done"

Одна из вещей - то, что только первые выстраивают в линию шоу в журнале hg:

$ hg log
changeset:   0:d2dc019450a2
tag:         tip
user:        Aaron Maenpaa <zacherates@gmail.com>
date:        Sat Jan 24 07:46:23 2009 -0500
summary:     Did some work

..., но если Вы разжигаете "hg представление", Вы видите, что целое сообщение там.

Отредактированный для добавления:

..., но hg-v журнал показывает целое сообщение:

$ hg -v log
changeset:   0:d2dc019450a2
tag:         tip
user:        Aaron Maenpaa <zacherates@gmail.com>
date:        Sat Jan 24 07:46:23 2009 -0500
files:       work
description:
Did some work
Now I'm done
5
задан Matt Clarke 21 October 2009 в 14:18
поделиться

6 ответов

Сворачивание последовательностей - это распространенный способ замены циклов аккумулятором.

let Lagrange(pos:_[], v:_[], desiredPos) =
  seq {0 .. v.Length-1} 
  |> Seq.fold (fun retVal i -> 
      seq {for j in 0 .. pos.Length-1 do if i <> j then yield j} 
      |> Seq.fold (fun w j -> w * (desiredPos - pos.[j]) / (pos.[i] - pos.[j])) 1.0
      |> (fun weight -> weight * v.[i] + retVal)) 0.0
4
ответ дан 18 December 2019 в 11:58
поделиться

Here's a non-recursive solution. It's a bit funky because the algorithm requires indices, but hopefully it shows how F#'s functions can be composed:

let Lagrange (pos : float[]) (vals : float[]) desiredPos = 
    let weight pos desiredPos (i,v) =
        let w = pos |> Array.mapi (fun j p -> j,p)
                    |> Array.filter (fun (j,p) -> i <> j)
                    |> Array.fold (fun acc (j,p) -> acc * (desiredPos - p)/(pos.[i] - p)) 1.
        w * v
    vals |> Array.mapi (fun i v -> i,v)
         |> Array.sumBy (weight pos desiredPos)
2
ответ дан 18 December 2019 в 11:58
поделиться

The part that makes your functional solution ugly is skipping the i'th element, which means indices. Pull that out into a reusable function so that all the ugly index handling is isolated. I call mine RoundRobin.

let RoundRobin l = seq {
  for i in {0..Seq.length l - 1} do
    yield (Seq.nth i l, Seq.take i l |> Seq.append <| Seq.skip (i+1) l)
}

It could be a lot uglier if you want to produce an efficient version, though.

I couldn't find product in the Seq module, so I wrote my own.

let prod (l : seq<float>) = Seq.reduce (*) l

Now producing the code is fairly simple:

let Lagrange pos value desiredPos = Seq.sum (seq {
  for (v,(p,rest)) in Seq.zip value (RoundRobin pos) do
    yield v * prod (seq { for p' in rest do yield (desiredPos - p') / (p - p') })
})

RoundRobin ensures that pos[i] is not included with the rest of pos in the inner loop. To include the val array, I zipped it with the round-robinned pos array.

The lesson here is that indexing is very ugly in a functional style. Также я обнаружил классный трюк: |> Seq.append <| дает вам инфиксный синтаксис для добавления последовательностей. Но не так хорошо, как ^ .

4
ответ дан 18 December 2019 в 11:58
поделиться

Я думаю, что это прекрасно работает как императивный код:

let LagrangeI(pos:_[], v:_[], desiredPos) =
    let mutable retVal = 0.0
    for i in 0..v.Length-1 do
        let mutable weight = 1.0
        for j in 0..pos.Length-1 do
            // The i-th term has to be skipped
            if j <> i then
                weight <- weight * (desiredPos - pos.[j]) / (pos.[i] - pos.[j])
        retVal <- retVal + weight * v.[i]
    retVal

но если вы хотите функциональность, некоторые свертки (вместе с mapi, поскольку вам часто нужно носить с собой индексы) работают хорошо:

let LagrangeF(pos:_[], v:_[], desiredPos) =
    v |> Seq.mapi (fun i x -> i, x)
      |> Seq.fold (fun retVal (i,vi) ->
        let weight = 
            pos |> Seq.mapi (fun j x -> j<>i, x) 
                |> Seq.fold (fun weight (ok, posj) ->
                    if ok then
                        weight * (desiredPos - posj) / (pos.[i] - posj)
                    else
                        weight) 1.0
        retVal + weight * vi) 0.0

Я не знаю математики здесь, поэтому я использовал несколько случайных значений для проверки (надеюсь), чтобы убедиться, что я ничего не напортачил:

let pos = [| 1.0; 2.0; 3.0 |]
let v = [|8.0; 4.0; 9.0 |]

printfn "%f" (LagrangeI(pos, v, 2.5))  // 5.375
printfn "%f" (LagrangeF(pos, v, 2.5))  // 5.375
3
ответ дан 18 December 2019 в 11:58
поделиться
            let rec GetWeight desiredPos i j (pos : float[]) weight = 
               if j = pos.Length then weight
               elif i = j then GetWeight desiredPos i (j+1) pos weight 
               else GetWeight desiredPos i (j+1) pos (weight * (desiredPos - pos.[j])/(pos.[i] - pos.[j]) ) 

            let rec Lagrange (pos : float[]) (vals : float[]) desiredPos result counter = 
               if counter = pos.Length then result
               else Lagrange pos vals desiredPos (result + (GetWeight desiredPos counter 0 pos 1.0)* vals.[counter]) (counter+1)

Лично я считаю, что простые конструкции if / elif / else выглядят здесь намного лучше без таких накладных расходов, как

match i with   
|i when i=...
1
ответ дан 18 December 2019 в 11:58
поделиться

Если вы просто возитесь, то вот версия, похожая на версию Брайана, которая использует каррирование функций и оператор канала кортежа.

let Lagrange(pos:_[], v:_[], desiredPos) =
    let foldi f state = Seq.mapi (fun i x -> i, x) >> Seq.fold f state
    (0.0, v) ||> foldi (fun retVal (i, posi) -> 
        (1.0, pos) ||> foldi (fun weight (j, posj) -> 
            if j <> i then
                (desiredPos - posj) / (posi - posj)
            else
                1.0)
        |> (fun weight -> weight * posi + retVal))
1
ответ дан 18 December 2019 в 11:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: