【问题标题】:Simulation design - flow of data, coupling仿真设计 - 数据流、耦合
【发布时间】:2009-02-23 23:11:29
【问题描述】:

我正在编写一个模拟,需要一些关于设计的提示。基本思想是生成给定随机过程的数据,然后用于各种计算。例如 1 次迭代:

  • 进程 1 -> 为源 1 生成数据:x1
  • 进程 2 -> 为源 1 生成数据:x2
  • 等等

稍后我想对源 2 的输出应用一些转换,这会导致 x2a、x2b、x2c。所以最终得到以下向量:[x1, x2a, x2b, x2c]。

我有一个问题,至于 N 多元随机过程(例如代表多个相关现象)我必须一次生成 N 维样本:

  • 进程 1 -> 为源 1...N 生成数据:x1...xN

我正在考虑一种简单的架构,它允许对模拟代码进行结构化并提供灵活性而不影响性能。

我在想一些类似的东西(伪代码):

class random_process
{
    // concrete processes would generate and store last data
    virtual data_ptr operator()() const = 0;
};

class source_proxy
{
    container_type<process> processes;
    container_type<data_ptr> data; // pointers to the process data storage
    data operator[](size_type number) const { return *(data[number]);}
    void next() const {/* update the processes */}
};

不知何故,我不相信这种设计。例如,如果我想使用样本向量而不是单次迭代,那么应该更改上述设计(例如,我可以让进程用数据填充传递给它们的代理矩阵的子矩阵,但又一次不确定这是否是一个好主意-如果是,那么它也很适合单次迭代情况)。欢迎大家提出意见、建议和批评。

编辑:

以上文字的简短总结,总结重点,澄清情况:

  • random_processes 包含生成一些数据的逻辑。例如,它可以从具有给定均值和相关矩阵的多元随机高斯中抽取样本。例如,我可以使用 Cholesky 分解 - 因此我将获得一组样本 [x1 x2 ... xN]
  • 我可以有多个具有不同维度和参数的 random_processes
  • 我想对random_processes 生成的单个元素进行一些转换

这是数据流程图

random_processes 输出 x1 --------------> x1 ----> x2a p1 x2 ------------变换|----> x2b ----> x2c x3 --------------> x3 p2 y1 ------------变换|----> y1a ----> y1b

输出被用来做一些计算。

【问题讨论】:

    标签: c++ simulation


    【解决方案1】:

    当我读到这个“答案”时,我的脑海中并没有出现,而是一个问题:

    (这个问题是市场上各种工具供应商为其创建可配置解决方案的一类问题的一部分。)

    您“必须”写这篇文章还是可以投资于久经考验的技术来让您的生活更轻松?

    在 Microsoft 的工作中,我与高性能计算供应商合作,其中一些供应商拥有数学库。这些公司的人会比我更接近于理解这个问题。 :)

    干杯, 格雷格·奥利弗 [MSFT]

    【讨论】:

      【解决方案2】:

      我会对此进行尝试,也许我遗漏了一些东西,但听起来我们有一个进程列表 1...N 不接受任何参数并返回一个 data_ptr。那么,如果在编译时已知数字,为什么不将它们存储在向量(或数组)中......然后以任何有意义的方式构造它们。您可以使用 stl 和内置容器(std::vector)函数对象(std::tr1::function)和算法(std::transform)走得很远......你没有说太多关于更高的层次结构,所以我假设一个非常愚蠢的天真结构,但显然你会适当地构建数据流。如果您有一个支持 C++0x lambda 的编译器,它会变得更加容易,因为您可以更轻松地嵌套转换。

      //compiled in the SO textbox...
      #include <vector>
      #include <functional>
      #include <numerics>
      typedef int data_ptr;
      
      class Generator{
      public:
          data_ptr operator()(){
            //randomly generate input
            return 42 * 4;
          }
      };
      class StochasticTransformation{
      public:
          data_ptr operator()(data_ptr in){
             //apply a randomly seeded function
             return in * 4;
          }
      };
      public:
          data_ptr operator()(){
            return 42;
          }
      };
      int main(){
      
          //array of processes, wrap this in a class if you like but it sounds 
          //like there is a distinction between generators that create data
          //and transformations
      
          std::vector<std::tr1::function<data_ptr(void)> generators;
      
          //TODO: fill up the process vector with functors...
          generators.push_back(Generator());
      
          //transformations look like this (right?)
          std::vector<std::tr1::function<data_ptr(data_ptr)> transformations;
      
          //so let's add one 
          transformations.push_back(StochasticTransformation);
      
          //and we have an array of results...
          std::vector<data_ptr> results;
      
          //and we need some inputs
          for (int i = 0; i < NUMBER; ++i)
             results.push_back(generators[0]());
      
          //and now start transforming them using transform...
          //pick a random one or do them all...
          std::transform(results.begin(),results.end(),
                         results.begin(),results.end(),transformation[0]);
      };
      

      【讨论】:

      • 感谢您的好主意。但是,仍然有一个问题困扰着我。我在问题中没有说得足够清楚,所以我会尝试重新措辞。
      • 感谢您的澄清。自从我查看 Cholesky 分解/因式分解以来已经有一段时间了,但我会在今晚或明天有机会希望更相关时修改我的答案。
      【解决方案3】:

      我认为第二个选项(上一段中提到的那个)更有意义。在您介绍的那个中,您正在玩​​指针和对随机过程数据的间接访问。另一个将所有数据(向量或矩阵)存储在一个地方 - source_proxy 对象。然后使用子矩阵调用随机过程对象以填充为参数,并且它们本身不存储任何数据。代理管理一切——从提供源数据(对于任何不同的源)到从生成器请求新数据。

      所以稍微改变一下你的 sn-p 我们可能会得到这样的结果:

      class random_process
      {
          // concrete processes would generate and store last data
          virtual void operator()(submatrix &) = 0;
      };
      
      class source_proxy
      {
          container_type<random_process> processes;
          matrix data;
          data operator[](size_type source_number) const { return a column of data}
          void next() {/* get new data from the random processes */}
      };
      

      但我同意另一位评论 (Greg) 的观点,即这是一个难题,取决于最终的应用程序可能需要深思熟虑。很容易走入死胡同导致重写大量代码...

      【讨论】:

      • 这就是我的想法,但正如我所说 - 我不确定其中是否隐藏了陷阱......
      猜你喜欢
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 2012-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      相关资源
      最近更新 更多