Node Linker

 Node Linker

Node Linker allows you to easily link one node ("i") with another node ("j") according to some user-defined probability. The idea here is that i will create a link with some other agent chosen at random. The choice of who to link with is determined by a vector of relative weights assigned to other agents that i may possibly link with. The probabilty of i linking with j is determined using these weights, and that these weights are updated over the iterations of the simulation in response to network evolution.

For example, the probability of i creating a link with j may be calculated by dividing j's current weight by the sum of all the weights in the weight vector. Assuming then that i does link with j, j's weight may then be updated by some amount increasing the probabilty that i will link with j again.

The actual usage of Node Linker is described below in the usage section below.


Appropriate Parent Component

Default Network Node. Node Linker must be added only to a Default Network Node.

Properties

Properties are the items that appear in the property pane when you click on a component in the project tree. For more information of properties, see here.

Name     Description
Actions See the section on Actions and editing them if you are unfamiliar with Actions.

Node Linker defines two actions by default.

  1. getProbabilty. This action is used to calculate the probabilty of one node linking to another.

  2. update. This action is used update the vector of node weights by the specified amount.

See the usage section below for more information.

Name This name is used internally by SimBuilder and should not contain any spaces.
Parameters See the the parameters section of the help docs for information on creating and editing parameters. Here you can define any parameters you want your node linker to have. See the usage section below for more information.
Start Weight The starting weight for nodes in the weight vector.



Fields

Fields are variables that the component exposes for your use in code. For example, if there is a field named sumt, you can refer to that field with self.sum in your NQPy code.

Name     Description
discount The past discount. A float value between 0 and 1. This can be set with the setPastDiscount action / method.                                                     
sum The current sum of the weight vector.



Java Parent Class

Many of the SimBuilder components are based on Java code. What this means is that these components come with built-in fields and methods inherited from their Java parent classes. The docs below describe these built in fields and methods.

Node Linker is based on the java class AbstractProbabilityRule. AbstractProbablilityrRules implements some generic functionality for ProbabilityRule-s. The idea here is that this AbstractProbabilityRule contains a vector of weights associated with a list of Objects. Sub-classes can use this vector of weights in their update and getProbability methods. For example, update may add or substract some amount from an objects associated weight and recalculate the probability accordingly.


The fields of a Java parent class can be used just as if they were parameters in your own model. For example, self.descriptors and so on. The format used below is

field name : field type
description

where the field type is a Java class type.

Java Parent Class Fields
weights : FloatArrayList
The list of wieghts for each object

weightMap : Hashtable
Maps Objects to the weights in the weight map.


The methods or actions of a Java parent class can be used just as if they were actions in your own model. For example, self.setRngSeed(33) and so on. The format used below is

method name(argument types, if any) : return type - an optional explanation of the return type
description

where the return type is a Java class type.

Java Parent Class Methods (Actions)
addNode( Object , float ) :
Adds a node with the specified weight.

addToNodeWeight( Object , float ) : float
Adds the specified value to the current weight for the specified node.

calcSum( ) :
Calculates the sum of the vector of weights.

getWeight( Object ) : float
Gets the weight of the specified node.

getWeightListIndex( Object ) : int
Returns the index position in the list of weights for the specified object. The returned value is the index for the weight value of the specified object.

makeProbabilityMap( RangeMap ) : RangeMap
Recreate the probability map for the list of Objects contained by this AbstractProbabilityRule using the specified RangeMap.

update( Object ) :
Updates the weights for the specified object by 1.


Usage

Adding a NodeLinker to an Agent component adds two parameters and some code to that Agent component. The two parameters are:

  1. _linker. _linker is of type Linker (see Linker in the RePast javadoc), and is what an agent will use to create links between itself and other nodes.

  2. startWeight. This corresponds to the start weight property above, and allows the you to change the start weight when the RePast simulation is running.

NodeLinker also adds code to the Agent's init action. The code looks like:

### uchicago.src.simbuilder.beans.NodeLinker Generated Code ###
rule = NodeLinker(self.model.getAgentList(), self.startWeight, self)
self._linker = Linker(rule)

The first line here is a comment and identifies the next two lines as SimBuilder (not user) generated code. The next two lines create a NodeLinker and then create _linker using that newly created NodeLinker. The important point here is that the NodeLinker here is created using the NodeLinker component as a template (much the same as agents are created), and that this NodeLinker is now part of _linker.

Three three important actions / methods that _linker has are:

  1. init. The init action initializes _linker for link creation by recreating the probability map. The probability map is created by calling the getProbability action of the NodeLinker, passing in each node to which a link could be created. The map itself maps nodes to probabilities, the larger the probability the more likely that node will be chosen as a the end of a link. init should be called before any calls to makeLink if the result of those calls is to reflect any updates.

  2. makeLink(from, edge, amtToUpdate). Using the current probabilty map (see 1. above) this method creates an edge between a randomly chosen node and the from node. It also calls NodeLinker's update action passing in the randomly chosen node and the amtToUpdate.

  3. makeLink(from, edge). This merely calls the above with amount to update of 1.

The important points here are how _linker uses NodeLinker's getProbability action to create the probability map, and how _linker uses NodeLinker's update action to update the weight vector.

Implementing getProbabilty and update: getProbability and update are unlike user defined actions in that they have arguments passed in to them. You can see these arguments in the variables pane of the Action editor. They are specific to these two actions respectively and are not prefixed by self.

  • getProbability. This action has a single passed in argument - otherNode. This "otherNode" is the node for which we want to calculate the probability. If, for example, we are calculating the probability by getting the current weight of otherNode and dividing it by the sum of the all the weights then the source code to getProbabilty would look like:

    return self.getWeight(otherNode) / self.sum

    Notice the return keyword here. getProbability must return some numeric value and the return keyword does this. If you do not include the return statement, you'll either get an appropriate error message or a cryptic one reporting Compiler Error: Compilation not supported on expr_stmt. In either case, you need to return a value.

  • update. This action has two passed in arguments, otherNode and amtToUpdate. The intention here is that you update the vector of weights using these values. otherNode is the node whose weight we want to update, and amtToUpdate is the amount we want to update the weight. Of course, you can do whatever transformations of this amtToUpdate value you like, or ignore it all together. The simplest update to the weight vector looks like:

    self.addToNodeWeight(otherNode, amtToUpdate)

    which simply adds otherNode amtToUpdate to the current weight of the otherNode.

The NodeLinker inherits several important methods / actions and variables from its java ancestors. These are described below.

  • sum. This is the current sum of the weight vector. It is recalculated each time _linker.init() is called.

  • getWeight(otherNode) - this returns the weight for otherNode.

  • addToNodeWeight(otherNode, amtToUpdate) - this adds the amtToUpdate to the current weight of otherNode.

Using a NodeLinker then is a matter of adding one to an agent component in the SimBuilder project pane, and then defining the getProbability and update methods to suit your own needs. The agent then uses the _linker parameter provided by the NodeLinker component to make links based on the probabilities update etc. defined in NodeLinker. This is typically done in the step action. For example the following step action code,

self.clearOutEdges()
self._linker.makeLink(self, DefaultDrawableEdge(), 1)

removes any previously created outgoing edges from the agent, and then creates a new link between this agent ("self") and one chosen at random. DefaultDrawableEdge is used as the edge, and the weight of the randomly chosen otherNode is updated by 1.

The sample simulations distributed with SimBuilder contain some simulations using the NodeLinker, so see those for more complicated examples.