10.5.1 Implementational Details About Connections

The is a general policy regarding the organization of functions and parameters for connections, connection groups, and connection specifications:

Only those functions that relate to the computational processing done by the connections should be defined in the connection spec, while the "structural" or other "administrative" functions should be defined in the connection group object so that the spec can be invariant with respect to these kinds of differences. The idea is that the spec defines functional aspects while the object defines various implementational aspects of an object's function (i.e. how the connections are arranged, etc..).

Thus, the Con_Group type has a large number of functions that are useful for making, finding, and removing connections. See the header file `src/pdp/netstru.h' for a listing of these. The Con_Group has a special way of representing connectivity. The group itself contains Connection objects, which define the state variables associated with the connection itself. However, the pointer to the unit on the other side of the connection (the sending unit in the case of receiving connections, and the receiving unit in the case of sending connections), is kept in a separate list, which is in one-to-one correspondence with the connection objects. This arrangement allows for the same connection state variables to be shared across connections between different units. Indeed, the sending and receiving connection groups from the same projection share a single connection object between them. Some of the projection types (see section 10.3.3.2 Tesselated (Repeated) Patterns of Connectivity, section 10.3.3.5 Miscellaneous other Projection Types) define additional forms of connection sharing.

Note that only one side of the connection is actually saved when a network is saved. This is the receiving side by default. Thus, after loading a project in from disk, the projection which manages the connections has to perform a ReConnect_Load function which builds the sending connections that correspond to the receiving connections that were just loaded in. A similar kind of operation must take place after copying a network.

For the functions that are defined in the ConSpec, a convention has been established regarding the division of labor between iterating through the connections in a group, and processing a given connection. Thus, there are two versions of each function defined in the con spec, one to apply to a single connection and another to apply to an entire Con_Group. The one which applies to a single connection has the name C_XXX where XXX is the name of the Con_Group version. Since some implementations of algorithms use bias weights, which are represented by a connection without a surrounding connection group, it is sometimes necessary to define a bias-weight version of a connection-specific function. Such a function will have the name B_XXX.

Note that the C_ version of the function is not declared virtual, while the Con_Group is. This was done for reasons of speed, since the C_ versions can be inlined within the iteration defined in the con-group version. However, it means that if you change one of the C_ functions, you must redefined the associated con-group version!

Also note that the same object type, a Con_Group (and its associated ConSpec), is used for both sending and receiving connections. Thus, the ConSpec will have functions that apply to both cases.

As with the unit specs, a standard way of breaking up neural computations has been established by defining some basic functions on the con spec. Only the Con_Group version of these functions are listed below, but a C_ version is also defined. Also note that the C_ versions of these functions typically take a connection pointer, receiving unit, and sending unit arguments. The functions are as follows:

InitWtState(Con_Group* cg, Unit* ru)
Initialize state variables (i.e. at beginning of training).
InitWtDelta(Con_Group* cg, Unit* ru)
Initialize variables that change every delta-weight computation. This clears any existing weight change computations.
float Compute_Net(Con_Group* cn, Unit* ru)
Computes the net input from the connections in this group, assuming that they are receiving connections.
Send_Net(Con_Group* cg, Unit* su)
Adds the net input contribution from the given sending unit to all of the receiving units on the other side of these connections. This assumes that the con group is a sending connection group of unit su.
float Compute_Dist(Con_Group* cg, Unit* ru)
Returns the distance (squared difference) between the unit activations and connection weights for all connections in group. This assumes it is a receiving group.
Compute_dWt(Con_Group* cg, Unit* ru)
Computes the delta-weight change for all connections in the group. This is typically called on the receiving connections, and is defined by specific algorithms.
UpdateWeights(Con_Group* cg, Unit* ru)
Updates the weights of the all the connections in the group. This again is defined by specific algorithms, but is called by generic functions up the network hierarchy.