MORe Usage

Installation

Quick Start for Repast Simphony models

Adapt and call the following method from your build(context) method after initialisation of agents:

// Define your social context if it is not the main context
Context<YourAgent> socialContext = context.getSubContext(socialContextId);

// Instantiate your edge factory in case you want to use custom edge objects.
// Otherwise, use MRepastEdge<AgentType> as edge type parameter and use new MRsEdgeFactory<AgentType, MRepastEdge<AgentType>() 
MRsEdgeFactory<YourAgent, YourEdge> eFac = new YourEdgeFactory();

MoreRsNetworkBuilder<YourAgent, YourEdge> networkBuilder = new MGeoRsWattsBetaSwBuilder(eFac,
                        socialNetworkName);
MoreRsNetwork<YourAgent, YourEdge> network = networkBuilder.buildNetwork(agents);
socialContext.addProjection(network);

// init More
MManager.init();
MManager.setSchedule(new MRsSchedule(RunEnvironment.getInstance().getCurrentSchedule()));
// Register network at MoRe
MNetworkManager.setNetwork(network, socialNetworkName);

Initialising MoRe

Consider the following steps to initialise MoRe properly:

  • Copy Your custom parameter data to the MoRe equivalents. To get an overview of used parameters in MoRe, consult the JavaDoc and see package de.cesr.more.params for descriptions of parameters. More only defines default values in these enumerations. Further parameter retrieval must be issued in the user code. For details, see the ParMa manual. Consider especially:
    • MSyQLPa for database setting relevant for storing network and node data
    • Parameters for network builders, e.g. MNetBuildBhPa for MBaselineDhhRadiusNetworkBuilder
    • Milieu-specific (i.e. agent type specific) parameters (see ) * Random seeds
  • Call MManager.init() to initialise default random streams (according to parameter settings for random seeds, see also )).

NOTE: Make sure to set up parameters before MManager.init() is called because otherwise defined parameters may not be considered during the initialisation of random number streams!

Using Logging

MoRe incorporates the Apache Log4J framework. See the website for configuring the logging framework properly in order to achieve the desired output. This is especially important to get meaningful warnings and error messages. Two basic configuration file can be found in config/log4j (with specific settings mostly out-commented). Note that the configuration file needs to be within the Java classpath.

Milieu-specific Parameters

Storing in DB

The MMilieuNetDataReader can be used to read milieu-specific parameters from a database (often used for generating heterogeneous, agent type specific networks). First, set according parameters in your model:

PmParameterManager.setParameter(MSqlPa.TBLNAME_NET_PREFS, "param_milieu_net");
PmParameterManager.setParameter(MSqlPa.TBLNAME_NET_PREFS_LINKS, "param_milieu_links");

PmParameterManager.setParameter(MNetworkBuildingPa.MILIEU_NETPREFS_PARAMID, new Integer(1));

Make also sure general DB settings are set correctly (see ). Then, call the data reader:

new MMilieuNetDataReader().initParameters();
Storing as CSV files

The MMilieuNetDataCsvReader and MMilieuNetLinkDataCsvReader parameter readers are able to import milieu-specific parameters from CSV files.

The first one requires parameters to be specified in the first row (header). The parameter MNetworkBuildingPa.MILIEU_NETWORK_CSV_COLUMNPREFIX defines a prefix for parameter definitions that needs to be omitted from the fully qualified classname in the header.

PmParameterManager.getNewInstance pm = PmParameterManager.getNewInstance();
pm.setParam(MNetworkBuildingPa.MILIEU_NETWORK_CSV_MILIEUS, "./path/to/SocialNetworkMilieuParameter.csv");
new MMilieuNetDataCsvReader(pm).initParameters();

The second reader loads milieu-specific composition preferences and may not contain a header:

PmParameterManager.getNewInstance pm = PmParameterManager.getNewInstance();
pm.setParam(MNetworkBuildingPa.MILIEU_NETWORK_CSV_MILIEU_LINKS, "./path/to/SocialNetworkMilieuLinksParameter.csv");
new MMilieuNetDataCsvReader(pm).initParameters();

Setting MNetworkBuildingPa.MILIEU_NETWORK_CSV_DELIMITER can be use to adjust the readers to the applied delimiter (default is ','):

pm.setParam(MNetworkBuildingPa.MILIEU_NETWORK_CSV_DELIMITER, ',')

The test classes de.cesr.more.testing.param.reader.MMilieuNetDataCsvReaderTest and de.cesr.more.testing.param.reader.MMilieuNetLinkDataCsvReaderTest contain working examples. According CSV files are located at ./test/res/.

Configuring Measures

The concept of network and node measures works as follows:

  1. Defining what measures (MoreMeasure) are calculated when using MNetworkMeasureManager or MNodeMeasureManager.
  2. MoRe then calculated the measures and stores the data at the nodes (these need to implement MoreNodeMeasureSupport).
  3. Calculated measures can be retrieved from the node objects.

Managing Node Measures

Basics

The central class for managing node measures is MNodeMeasureManager. To obtain an instance of the node measure manager call MNodeMeasureManager.getInstance(). However, make sure to set the schedule before:

MNetworkManager.setSchedule(MoreSchedule schedule)

To use the Repast Simphony schedule (adapter from RS's ISchedule to MoreSchudule) call

MNetworkMeasureManager.setSchedule(new MRsSchedule(RunEnvironment.getInstance().getCurrentSchedule()));

Setting Parameters for Node Measure Calculation

Every MoreMeasure has a parameter map. The map contains key - (default)value pairs of parameters. the user may walk through the map and alter parameter values to adjust measure calculations. For instance, to set scheduling parameters:

// set scheduling parameters:
Map < String , Object > params = new HashMap < String , Object >();
params.put(MNetworkMeasureManager.ParameterKeys.START.name(), new Integer(1));
int interval = (Integer) PmParameterManager.getParameter(SocNetPa.ANALYSE_NETWORKS_INTERVAL);
params.put(MNetworkMeasureManager.ParameterKeys.INTERVAL.name(), new Integer(interval));
params.put(MNetworkMeasureManager.ParameterKeys.END.name(), MScheduleParameters.END_TICK);
params.put(MNetworkMeasureManager.ParameterKeys.PRIORITY.name(), MScheduleParameters.FIRST_PRIORITY);

NOTE: It is not guaranteed that a MoreMeasure provides a non-empty map!

Trigger measure calculation for nodes

The params map (see above) is then passed when triggering a measure calculation:

// add measures for overall network:
MNodeMeasureManager.getInstance().addMeasureCalculation(ModelManager.SOCNET_NAME,
                MBasicNodeMeasureSupplier.Short.N_STAT_AVGPATH.getName(), params);      

Node Measure Support

More offers features to access node measures. The agent class needs to implement the interface MoreNodeMeasureSupport:

protected MNodeMeasures measures = new MNodeMeasures();
        @Override
        public void setNetworkMeasureObject(
                        MoreNetwork<? extends MoreNodeMeasureSupport, ?> network,
                        MMeasureDescription key, Number value) {
                measures.setNetworkMeasureObject(network, key, value);
        }

        @Override
        public Number getNetworkMeasureObject(
                        MoreNetwork<? extends MoreNodeMeasureSupport, ?> network,
                        MMeasureDescription key) {
                if (measures.getNetworkMeasureObject(network, key) == null) {
                        // <- LOGGING
                        logger.error("No measure defined for key " + key);
                        // LOGGING ->
                }
                return measures.getNetworkMeasureObject(network, key);
        }

Managing Network Measures

Basics

The central class for managing network measures is MNetworkMeasureManager. To obtain an instance of the network manager call <<<MNetworkMeasureManager.getInstance(). However, make sure to set the schedule before: MNetworkManager.setSchedule(MoreSchedule schedule)!

Trigger measure calculation for networks

The params map (see above) is then passed when triggering a measure calculation:

MNetworkManager netMan = MNetworkManager.getInstance();
netMan.addMeasureCalculation(net, MCentralityNetMSupplier.Short.NET_CEN_DEGREE.getName(), params);

Setting Parameters for Network Measure Calculation

see above

Adding Measure Definitions

As default, the MNetworkMeasureManager imports measure definitions from MBasicNetworkMeasureSupplier (see JavaDoc for details). Further measure definitions are added by passing an instance of MoreMeasureSupplier to MNetworkMeasureManager#addMeasureSupplier(supplier). See Implementing Custom Measures for further instructions.

Defining subnetworks

MoRe supports the definition of subnetworks according to criteria that may be derived from Java object properties to calculate network measures for certain network parts, for instance. As a default, subnetworks consist of nodes that fulfill given criteria and all links of the original network between these nodes. To define a subnetwork accomplish the following steps:

  • Define a org.apache.commons.collections15.Predicate whose evaluate(object) methods returns true for all vertices that shall be included in the subnetwork.
    MNetworkManager.storeVertexSubnetwork(network, predicate, subnetwork_name)
    

    Network may be the name of a network already registered at the MNetworkManager or an instance of MoreNetwork.

Implementing Custom Measures

  1. Create a subclass of MAbstractMeasureSupplier.
  2. It is a good idea to define the measures' names as enum Short.
    public enum Short {
            YOUR_MEASURE("YourMeasureName");
    
            String  name;
    
            private Short(String name) {
                    this.name = name;
            }
    
            public String getName() {
                    return name;
            }
    }
    
  3. In the constructor, add the categories the defined measures belong to (see MNetworkMeasureCategory; you may also define your own MoreMeasureCategory).
    private DirectedInfoMapModularitySupplier() {
            categories.add(MNetworkMeasureCategory.NETWORK_MODULARITY);
            addMeasures();
    }
    

    A MNetworkMeasureSupplier should be implemented as singleton since it does not make sense to have more than one supplier. However, the MAbstractMeasureSupplier overrides equals() and compares regarding the class name but does not prevent subclasses from overriding its equals() method.

  4. Add the measure calculation:
    private void addMeasures() {
            MMeasureDescription description = new MMeasureDescription(
                            MNetworkMeasureCategory.NETWORK_MODULARITY,
                            Short.YOUR_MEASURE.getName(),
                            "Your measure description");
    
            measures.put(description, new MAbstractNetworkMeasure(description,
                            Double.class) {
    
                    @Override
                    public <T, EdgeType extends MoreEdge<? super T>> MoreAction getAction(
                                    final MoreNetwork<T, EdgeType> network,
                                    Map<String, Object> parameters) {
                            return new MAbstractAction() {
    
                                    @Override
                                    public void execute() {
                                            double value = <calculate your measure here>;
                                            MNetworkManager.setNetworkMeasure(
                                                            network,
                                                            new MMeasureDescription(
                                                                            Short.NET_MOD_UNDIRECTED_INFOMAP
                                                                                            .getName()), value);
                                    }
    
                                    @Override
                                    public String toString() {
                                            return Short.YOUR_MEASURE.getName() + "(" + network.getName() + ")";
                                    }
                            };
                    }
            });
    }
    
  5. Add your measure supplier:
    MNetworkMeasureManager.getInstance().addMeasureSupplier(
                                            YourMeasureSupplier.getInstance());
    

    The scheduling parameters (start, interval, end) are defined in the parameter map that is interpreted by MNetworkMeasureManager or MNodeMeasureManager. Therefore, generating MoreActions does not need to define a MSchedulingParameter.

Defining Dynamics of Networks

Manipulation Edges

With MoreEgoNetworkManagerComp MoRe provides an agent component that can manage agent's links. Agents may implement MoreEgoNetworkManagingAgent to guarantee access to the component.

Processing Network Management

The MoreEgoNetworkManagerComp delegates MoreEgoNetworkEvents to potentially different MoreEgoNetworkProcessors. To configure the MoreEgoNetworkManagerComp using a map as configuration object, code accordingly:

MoreEgoNetworkProcessor<MoreNetworkAgent, MoreEdge>> yourEdgeProcessor = 
        new MoreEgoNetworkProcessor<MoreNetworkAgent, MoreEdge>>() {
                public void process(A agent, MoreNetwork<A, E> network) {
                        // do something
                }
        };
        
Map<MoreEgoNetworkEvent, MoreEgoNetworkProcessor<MoreNetworkAgent, MoreEdge>> map = 
        MEgoNetworkManagerComp.getEmptyProcessorMap();
map.put(MLinkManagingEvent.getInstance(), yourEdgeProcessor);
agent.setEgoNetworkManager(new MEgoNetworkManagerComp<MoreNetworkAgent, MoreEdge>(map));
Processing Network Management

MoreEgoNetworkProcessor can handle different kinds of MoreEgoNetworkEvents which currently are:

There are a number of MoreEgoNetworkProcessor for specific effects available that can be put into the configuration map directly or be extended (it is recommended to consult the source code since their effects can be quite complex):

To activate link management, the MoreEgoNetworkManagerComp needs to be called with the according event:

agent.getEgoNetworkManager().process(MLinkManagingEvent.getInstance(), agent, network);

Constant Fading of Edge Weights

MoRe provides the MoreFadingWeightEdge interface which is implemented by all More internal implementations of MoreEdge and support the automatic, constanst dedcrease or increase of all edge weights. The according method is scheduled using a MoreAction.

Manipulating Repast Simphony networks

The RS networks usually deal with changes of edges in the geography via MoreGeoNetworkEdgeModifier, but do not care about adding and removing nodes to and from contexts and geographies. The reason is that these node objects are expected to survive even if they are deleted from the network.

Network GraphML Output

Networks can be stored using MoreIoUtilities: +-- MoreIoUtilities.outputGraph(r.getNetwork(), new File(tickFilename(r))); +--

Writing node attributes

It is furthermore possible to write specific node attributes into the GraphML file:

Map<String, GraphMLMetadata<Agent>> vertexMetadata = new HashMap<String, GraphMLMetadata<Agent>>();
vertexMetadata.put("X", new GraphMLMetadata<Agent>("X coordinate", "NA",
        new Transformer<Agent, String>() {
                @Override
                public String transform(Agent agent) {
                        return agent.getX();
                }
}));
MoreIoUtilities.outputGraph(r.getNetwork(), new File(tickFilename(r)), vertexMetadata, null);

Random Numbers in MoRe

MoRe uses its own instance of URandomService. Basically, it defines two different random number generators:

  • RND_STREAM_NETWORK_BUILDING
  • RND_STREAM_NETWORK_DYNAMICS

    By default, and when only a global random seed (RANDOM_SEED) is defined, these point to a single global random number generators (RND_STREAM). However, these streams can be fed by distinct random seeds:

  • RANDOM_SEED_NETWORK_BUILDING
  • RANDOM_SEED_NETWORK_DYNAMICS

    The streams are initialised by calling

    MManager.init()
    

    To influence the entire random number generation in MoRe it is sufficient to set the parameter RANDOM_SEED:

    PmParameterManager.setParameter(MRandomPa.RANDOM_SEED, new Integer(1));
    

    To influence the random number generation of certain parts of MoRe change the according random number seed, e.g.:

    PmParameterManager.setParameter(MRandomPa.RANDOM_SEED_NETWORK_BUILDING, new Integer(2));
    

    Furthermore, it is possible to register custom random number generators for a certain part of MoRe:

    MManager.getURandomService().registerGenerator((String) PmParameterManager
            .getParameter(MRandomPa.RND_STREAM_NETWORK_BUILDING), new MersenneTwister(3));
    

    Alternatively, you may register your custom random number generator and adapt the stream name parameter accordingly.

    See the URaNuS manual for further information, especially Full Flexibility.