Graph 在f中创建路径列表#
(这可能是一部经典之作,但我想知道如何最好地表达它) 我从左边开始,在某个日期。 对于某些资产,我可以计算从开始日期到未来某个日期的回报。 从那个未来的日子起,我可以递归地在时间上走得更远 我想生成所有尽可能向右的路径,但在某个目标日期之前停止 这是我的密码。”a是一项资产,(DateTime*DateTime)是我对所述基础资产报价的2倍Graph 在f中创建路径列表#,graph,f#,primitive,Graph,F#,Primitive,(这可能是一部经典之作,但我想知道如何最好地表达它) 我从左边开始,在某个日期。 对于某些资产,我可以计算从开始日期到未来某个日期的回报。 从那个未来的日子起,我可以递归地在时间上走得更远 我想生成所有尽可能向右的路径,但在某个目标日期之前停止 这是我的密码。”a是一项资产,(DateTime*DateTime)是我对所述基础资产报价的2倍 member this.getPaths dtstart dtend : Set<('a*(DateTime*DateTime)) list>
member this.getPaths dtstart dtend : Set<('a*(DateTime*DateTime)) list>=
let rec getPaths dtstart dtend (pastpath:List<'a*(DateTime*DateTime)>) : seq<('a*(DateTime*DateTime)) list>=
let udls = this.getUnderlyingsQuotingAt dtstart
let onestep = seq { for udl in udls do
let qt = this.QuoteNextAfterSrict udl dtstart
if qt.IsNone || (qt.Value |> fst > dtend) then
yield pastpath |> List.rev
else
let nextdate = qt.Value |> fst
yield! (getPaths nextdate dtend ((udl, (dtstart, nextdate))::pastpath) ) }
onestep
getPaths dtstart dtend List.empty |> Set.ofSeq
member this.getpath dtstart dtend:Set):seq=
让计数=参考0
printfn“从%A到%A的计算路径”dtstart dtend
让rec getpath dtstart dtend(passpath:List=
让udls=this.GetUnderlineSquoting在dtstart处
让udlquotes=udls |>Seq.map(有趣的udl->(udl,this.quotenexterstrict udl dtstart))
|>顺序过滤器(乐趣(uq)->q.IsSome)
|>Seq.map(fun(udl,q)->(udl,q.Value))
|>Seq.filter(乐趣)->fst q List.rev
其他的
对于udl中的(udl,q)引号do
设nextdate=(fst q)
计数:=!计数+1
如果!计数%1000=0,则打印fn“!计数%A,路径:%A”!计数路径
收益率!(getPaths下一个日期dtend((udl,(dtstart,下一个日期))::pastpath))
}
一步
GetPath dtstart dtend List.empty |>Set.ofSeq
我不太了解您的算法,但我认为总体结构看起来不错。您所说的“重复数据消除”是什么意思?如果您指的是递归处理结束时使用的List.rev
调用,那么这是非常常见的模式(我认为没有更好的方法)
关于F#编码风格,有点令人失望的是,在分析qt
值时,您无法轻松使用模式匹配(因为无法使用内置模式对条件进行编码)。但是,您可以定义当输入大于参数时匹配的辅助参数化活动模式:
let inline (|MoreThan|_|) limit input =
if input > limit then Some input else None
使用该模式,您可以使seq
的正文更具可读性:
let rec getPaths dtstart dtend pastpath = seq {
let udls = this.getUnderlyingsQuotingAt dtstart
for udl in udls do
match this.QuoteNextAfterSrict udl dtstart with
| None
| Some (MoreThan dtend _, _) ->
yield pastpath |> List.rev
| Some (nextdate, _) ->
let newpath = (udl, (dtstart, nextdate))::pastpath
yield! getPaths nextdate dtend newpath }
我知道这并没有回答您的问题,但您可以使用类型别名使代码更易于阅读至少在两个地方。这可能更容易阅读。键入DateSpan您完全正确。谢谢您的建议。我将添加一些关于代码的注释。对于重复,让我们假设我有10个参考底图,以及(qt.Value |>fst>dtend)中的所有测试导致终止。我将有一个由10个空序列组成的序列。我将研究你的建议,这看起来更为惯用。谢谢。@nicolas啊,我开始理解了-因此,基本上,如果
QuoteNextAfterStrict udl dtstart
retruns值与第一个模式(在我的版本中)匹配对于udls
中的任何udl
,则您希望生成pastpath |>List.rev
一次,否则您希望生成它零次?@nicolas如果是这样的话,我可能会使用List.map对udls
中的所有值运行QuoteNextAfterStrict
,然后测试所有值是否匹配第一个pattern-如果是,可以返回pastpath |>List.rev
。然后可以迭代与第二种模式匹配的模式并递归生成。可以使用List.partition
将它们拆分为两种情况。
let rec getPaths dtstart dtend pastpath = seq {
let udls = this.getUnderlyingsQuotingAt dtstart
for udl in udls do
match this.QuoteNextAfterSrict udl dtstart with
| None
| Some (MoreThan dtend _, _) ->
yield pastpath |> List.rev
| Some (nextdate, _) ->
let newpath = (udl, (dtstart, nextdate))::pastpath
yield! getPaths nextdate dtend newpath }