Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Data Structures   File List   Namespace Members   Data Fields   Globals   Related Pages   Examples  

matrioschka.cpp

Recursive simulations are introduced.

One of the unique features of ODEMx is the possibility to run a simulation inside another simulation without unwanted side-effects. This could come in handy if you want to simulate an agent network for instance. Agents have an internal model of their environment, which they use to make their decisions. With ODEMx such an agent could be modelled with an internal (simplified) simulation. Another example could be a very complex simulation task. With ODEMx you could split the model into several blocks, develop each one as a simulation on its own, and plug them together at the end.

//----------------------------------------------------------------------------
//      Copyright (C) 2002, 2003 Humboldt-Universitaet zu Berlin
//
//      This library is free software; you can redistribute it and/or
//      modify it under the terms of the GNU Lesser General Public
//      License as published by the Free Software Foundation; either
//      version 2.1 of the License, or (at your option) any later version.
//
//      This library is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//      Lesser General Public License for more details.
//
//      You should have received a copy of the GNU Lesser General Public
//      License along with this library; if not, write to the Free Software
//      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//----------------------------------------------------------------------------
#include <odemx/base/Process.h>

#include <iostream>

using namespace std;
using namespace odemx;

//
// In this example we demonstrate the possibility to cascade simulations in a recursive 
// simulation called Matrioschka. Like the Russian puppet inside a puppet inside a puppet 
// inside ...
// 
// A user defined simulation is a class derived from Simulation. Every process or model
// component requires a pointer to its simulation. The user defined simulation can provide
// its processes with additional data. Furthermore, a user defined simulation must implement
// the 'initSimulation()' function to start its processes and to do specific initialisations.
//
class Matrioschka : public Simulation {
        //
        // The simulation contains only the process Proc.
        // This process expects a Matrioschka-simulation as
        // environment. Defining the process as an inside 
        // class of Matrioschka is of course not required.
        //
        class Proc : public Process {
        public:
                Proc(Matrioschka* sim, ProcessObserver* o = 0)
                        : Process(sim, "Proc", o) {}

        protected:
                //
                // In its 'main()' function the process gets a pointer to
                // its simulation. After a cast (the dynanmic_cast could 
                // be spared) the process can access the data provided by 
                // its simulation.
                //
                virtual int main() {
                        int i;
                        Matrioschka* sim=dynamic_cast<Matrioschka*>(getSimulation());
                        int level=sim->getLevel();

                        for (i=level; i>0; --i)
                                cout << ' ';

                        if (level%2>0)
                                cout << "Di " << level << endl;
                        else
                                cout << "Da " << level << endl;

                        //
                        // After some outputs the process realises the recursion.
                        // 
                        if (level>0) {
                                Matrioschka m(sim->getLevel()-1);
                                m.run();
                        }

                        for (i=level; i>0; --i)
                                cout << ' ';

                        if (level%2>0)
                                cout << "Di " << level << endl;
                        else
                                cout << "Da " << level << endl;

                        return 0;
                }
        };

        Proc* p;
        unsigned int mLevel;

public:
        //
        // Because of the recursion Matrioschka needs the additional
// parameter 'level'.
        //
        Matrioschka(unsigned int level, SimulationObserver* o=0)
                : Simulation("Matrioschka", o), mLevel(level) {}

        ~Matrioschka() {
                delete p;
        }
        
        //
        // 'level' is the recursion parameter of the Matrioschka simulation.
        //
        unsigned int getLevel() {return mLevel;}

protected:
        //
        // If you are defining your own simulation class you have to provide 'initSimulation'
        // to initialise the simulation. This function is called when the simulation is started
        // for the first time.
        //
        virtual void initSimulation() {
                p = new Proc(this);
                p->activate();
        }       
};

//
// The 'main' function looks a bit deserted in this example. Almost everything is done in
// the simulation. The advantage is, you can 'reuse' the simulation as it is.
//
int main(int argc, char* argv[]) {
        Matrioschka m(10);
        m.run();

        return 0;
}


Generated on Mon Aug 11 10:36:06 2003 for ODEMx by doxygen1.3