Concurrency Haskell用于模拟多车道交通圈?

Concurrency Haskell用于模拟多车道交通圈?,concurrency,haskell,Concurrency,Haskell,我很难想出一个真实的并发示例: 想象一下上述情况,在哪里 有很多车道,很多路口 还有大量的汽车。此外 这是人为因素 对于交通工程师来说,这个问题是一个困难的研究领域。不久前,当我调查它时,我注意到许多模型都失败了。当人们谈论函数式编程时,上面的问题往往会浮现在我的脑海中 你能用Haskell模拟一下吗?哈斯凯尔真的是如此并发吗?在Haskell中并行此类并发事件的限制是什么 如果需要一个具有函数顺序子集的并发编程语言,请考虑Erlang . Erlang、Scala和Clojure是可能适合您的

我很难想出一个真实的并发示例:

想象一下上述情况,在哪里 有很多车道,很多路口 还有大量的汽车。此外 这是人为因素

对于交通工程师来说,这个问题是一个困难的研究领域。不久前,当我调查它时,我注意到许多模型都失败了。当人们谈论函数式编程时,上面的问题往往会浮现在我的脑海中

你能用Haskell模拟一下吗?哈斯凯尔真的是如此并发吗?在Haskell中并行此类并发事件的限制是什么


如果需要一个具有函数顺序子集的并发编程语言,请考虑Erlang .


Erlang、Scala和Clojure是可能适合您的语言

但我认为您需要更多的是找到一个合适的多代理模拟库或工具包,并绑定到您最喜欢的语言


我可以告诉你关于梅森、蜂群和就餐的事。但是这些是Java和C库…

我不确定问题的确切含义。Haskell 98没有为并发指定任何内容。特定的实现,如GHC,提供了实现并行性和并发性的扩展

要模拟交通,这将取决于您在模拟中需要什么,例如,如果您希望跟踪单个车辆或以一般统计方式进行跟踪,您是否希望使用滴答声或连续时间模型等,您可以提出一种数据表示法,用于并行或并发评估

GHC提供了多种方法来利用多个硬件执行单元,从传统的信号量和互斥量,到轻量级线程(可用于实现类似Erlang的线程),再到纯功能的、带互斥量的和实验性的


是的,Haskell有很多并行执行的方法,当然可以在交通模拟中使用,但是在为并行模拟选择最佳的数字表示之前,您需要清楚地知道您要做什么。每种方法都有自己的优点和局限性,包括学习曲线。您甚至可能会了解到,就模拟的规模而言,并发是一种过分的手段。

我想您可能会问,是否可以为系统中的每个对象使用一个线程

GHC运行时,并通过Chris Smith提到的抽象将这些线程多路复用到可用硬件上。因此,如果您使用的是Haskell/GHC,那么您的系统中当然有可能有数千个线程


就性能而言,它倾向于这样做,但不太强调进程在多个节点之间的分布。尤其是GHC,它更倾向于在共享内存多核系统上实现快速并发。

在我看来,您似乎在尝试进行模拟,而不是真实世界的并发。这类事情通常是通过使用。几年前,我在Haskell中做了类似的事情,并基于延续monad transformer推出了自己的离散事件模拟库。恐怕它归我的雇主所有,所以我不能把它发出去,但也不太难。延续实际上是一个挂起的线程,因此(从内存中)定义如下内容:

状态中的ThreadQueue包含当前调度线程的队列。您还可以使用其他类型的线程队列来保存未调度的线程,例如在信号量中(基于“IORef(Int,ThreadQueue)”)。一旦有了信号量,就可以构建等价的MVAR和MQUE

要计划线程,请使用“callCC”。“callCC”的参数是一个函数“f1”,它本身将函数“c”作为参数。这个内部参数“c”是延续:调用它将恢复线程。当您执行此操作时,从该线程的角度来看,“callCC”只是将您作为参数提供的值返回给“c”。实际上,您不需要将值传递回挂起的线程,因此参数类型为null


因此,您对“callCC”的参数是一个lambda函数,它接受“c”,并将其放在适合您所做操作的任何队列的末尾。然后它从状态内部获取线程队列的头并调用它。您不必担心此函数返回:它永远不会返回。

我已经对此做了一个回答,但现在我想从更广泛的角度添加另一个

听起来,让这成为一个难题的原因是,每个司机的行动都是基于对其他司机将要做什么的心理预测。例如,当我开车时,我可以根据他与我和前面汽车之间的距离排列自己的方式,判断出一辆汽车何时可能会在我前面停下,甚至在他表示之前。反过来,他也可以从我退后给他腾出空间的事实中看出我见过他,所以可以停下来。一个好的司机会发现很多这些微妙的线索,而且很难建模

因此,第一步是找出失败模型中不包括真实驾驶的哪些方面,并找出如何将其纳入其中

(线索:所有模型都是错误的,但有些模型是有用的)

我怀疑答案将涉及给每个模拟驾驶员一个或多个心理模型,让他们知道每个驾驶员将要做什么。这涉及到使用驱动程序1可能对驱动程序2的意图做出的几种不同假设来运行驱动程序2的规划算法。同时,驱动程序2也在对驱动程序1进行同样的操作

这是一种很难添加到现有模拟器中的东西,特别是如果它是用传统语言编写的,因为规划算法可能会产生副作用,即使它只是以遍历数据结构的方式进行。但是函数式语言可能做得更好

此外,它们之间的相互依存关系
type Sim r a = ContT r (StateT ThreadQueue IO a)

newtype ThreadQueue = TQ [() -> Sim r ()]