GrFNN input

Current code (April 28, 2015):

def compute_input(layer, z, connections, x_stim=0):
    """Compute the overall input to a GrFNN (:math:`x` in equation
    15 in the cited paper)

    Args:
        layer (:class:`grfnn`): layer which will be receiving this input
        z (:class:`numpy.array`): state of the GrFNN at the instant
            when the input needs to be computed.
        connections (list): list of tuples of the form
            (*source_z*, *connection*) where *source_z* is the
            state of the source :class:.`GrFNN` and *connection* is a
            connection object (:class:`Connection`)
        x_stim (:class:`numpy.array`): external stimulus

    Returns:
        :class:`numpy.array` -- array of inputs, one element per
        oscillator in the GrFNN

    Note:
        Here ``connections`` refer to inter-layer connections,
        as well as intra-layer connections (self connected layers)

    Note:
        `z` does not necessarily correspond to `self.z`, as this method
        might be called at in "intermediate" integration (RK4) step

    """

    # process external signal (stimulus)
    if layer.stimulus_conn_type == 'linear':
        x = layer.w * x_stim
    elif layer.stimulus_conn_type == 'active':
        x = layer.w * x_stim * active(z, layer.zparams.sqe)
    elif layer.stimulus_conn_type == 'allfreq':
        x = layer.w * passiveAllFreq(x_stim, layer.zparams.sqe) * \
            active(z, layer.zparams.sqe)
    elif layer.stimulus_conn_type == 'all2freq':
        x = layer.w * passiveAll2Freq(x_stim, layer.zparams.sqe) * \
            active(z, layer.zparams.sqe)
    else:
        raise Exception("Unknown stimulus connection type '{}'".format(
            layer.stimulus_conn_type))

    # process coupled GrFNNs (internal, afferent and efferent)
    for (source_z, conn) in connections:
        matrix, conn_type = conn.matrix, conn.conn_type
        if conn_type == '1freq':
            x = x + conn.weights * matrix.dot(source_z)
        elif conn_type == '2freq':
            x = x + conn.weights * twoFreq(z, source_z,
                                           conn.farey_num, conn.farey_den,
                                           matrix,
                                           layer.zparams.e)
        elif conn_type == '3freq':
            x = x + conn.weights * threeFreq(z, source_z,
                                             conn.monomials,
                                             layer.zparams.e)
        elif conn_type == 'allfreq':
            x = x + conn.weights * \
                matrix.dot(passiveAll2Freq(source_z, layer.zparams.sqe)) * \
                active(z, layer.zparams.sqe)
        elif conn_type == 'all2freq':
            x = x + conn.weights * \
                matrix.dot(passiveAllFreq(source_z, layer.zparams.sqe)) * \
                active(z, layer.zparams.sqe)
        else:
            raise Exception("Unknown connection type '{}'".format(conn_type))

    return x

Explanation

Let $w_i$ denote layer.w. Be default $w_i = f_i = \omega_i/2\pi$. $w_i$ can also be set by hand (see w parameter in pygrffn::GrFNN. It it usually set to the same value for the whole GrFNN. This has an huge importance, as we'll see.

The goal is to

The input calculation happens in 2 steps:

  1. external stimulus
  2. coupling with other GrFNNs

1. External Stimulus

There are 4 possible connection types: linear, active, allFreq, all2Freq.

1.1 linear

1.2 active

1.3 allFreq

1.4 all2Freq


In [ ]: