Exemple #1
0
def test_distributions():
    check_init_args(PDF, ["x", "p"])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))
    assert (repr(PDF(
        [1, 2], [0.4, 0.6])) == "PDF(x=array([1., 2.]), p=array([0.4, 0.6]))")

    check_init_args(Uniform, ["low", "high", "integer"])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))
    assert repr(Uniform(0, 1)) == "Uniform(low=0, high=1)"
    assert repr(Uniform(
        0, 5, integer=True)) == "Uniform(low=0, high=5, integer=True)"

    check_init_args(Gaussian, ["mean", "std"])
    check_repr(Gaussian(0, 2))
    assert repr(Gaussian(1, 0.1)) == "Gaussian(mean=1, std=0.1)"

    check_init_args(Exponential, ["scale", "shift", "high"])
    check_repr(Exponential(2.0))
    check_repr(Exponential(2.0, shift=0.1))
    check_repr(Exponential(2.0, shift=0.1, high=10.0))
    assert repr(Exponential(2.0)) == "Exponential(scale=2.0)"

    check_init_args(UniformHypersphere, ["surface", "min_magnitude"])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))
    assert repr(UniformHypersphere()) == "UniformHypersphere()"
    assert repr(
        UniformHypersphere(surface=True)) == "UniformHypersphere(surface=True)"

    check_init_args(Choice, ["options", "weights"])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))
    assert repr(Choice([1, 2, 3])) == "Choice(options=array([1., 2., 3.]))"
    assert (repr(
        Choice([1, 2, 3], weights=[0.1, 0.5, 0.4])
    ) == "Choice(options=array([1., 2., 3.]), weights=array([0.1, 0.5, 0.4]))")

    check_init_args(Samples, ["samples"])
    check_repr(Samples([3, 2, 1]))
    assert repr(Samples([3, 2, 1])) == "Samples(samples=array([3., 2., 1.]))"

    check_init_args(SqrtBeta, ["n", "m"])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))
    assert repr(SqrtBeta(3)) == "SqrtBeta(n=3)"
    assert repr(SqrtBeta(3, 2)) == "SqrtBeta(n=3, m=2)"

    check_init_args(SubvectorLength, ["dimensions", "subdimensions"])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))
    assert repr(SubvectorLength(3)) == "SubvectorLength(dimensions=3)"

    check_init_args(CosineSimilarity, ["dimensions"])
    check_repr(CosineSimilarity(6))
    assert repr(CosineSimilarity(6)) == "CosineSimilarity(dimensions=6)"
Exemple #2
0
def test_exponential(scale, shift, high, rng):
    n = 100
    dist = Exponential(scale, shift=shift, high=high)
    samples = dist.sample(n, rng=rng)
    assert np.all(samples >= shift)
    assert np.all(samples <= high)
    # approximation of 95% confidence interval
    ci = scale * 1.96 / np.sqrt(n)
    if scale + ci < high:
        assert abs(np.mean(samples - shift) - scale) < ci
Exemple #3
0
def RhythmicDMP(n_per_d, freq, forcing_f, tau=0.025, net=None):
    if net is None:
        net = nengo.Network(label="Rhythmic DMP")

    out_dims = forcing_f(0.).size
    omega = freq * tau * 2 * np.pi
    with net:
        # --- Decode forcing_f from oscillator
        net.osc = nengo.Ensemble(n_per_d * 2,
                                 dimensions=2,
                                 intercepts=Exponential(0.15, 0.3, 0.6),
                                 label=forcing_f.__name__)
        nengo.Connection(net.osc,
                         net.osc,
                         synapse=tau,
                         transform=[[1, -omega], [omega, 1]])
        net.output = nengo.Node(size_in=out_dims)
        nengo.Connection(net.osc,
                         net.output,
                         function=radial_f(forcing_f),
                         synapse=None)

        # --- Drive the oscillator to a starting position
        net.reset = nengo.Node(size_in=1)
        d_intercepts = Exponential(0.2, -0.5, 0.1)
        net.diff_inhib = nengo.Ensemble(20,
                                        dimensions=1,
                                        intercepts=d_intercepts,
                                        encoders=Choice([[1]]))
        net.diff = nengo.Ensemble(n_per_d, dimensions=2)
        nengo.Connection(net.reset, net.diff_inhib, transform=-1, synapse=None)
        nengo.Connection(net.diff_inhib.neurons,
                         net.diff.neurons,
                         transform=-np.ones((n_per_d, 20)))
        nengo.Connection(net.osc, net.diff)
        reset_goal = np.array([-1, omega * 0])
        nengo.Connection(net.diff, net.osc, function=lambda x: reset_goal - x)

        # --- Inhibit the oscillator by default
        i_intercepts = Exponential(0.15, -0.5, 0.1)
        net.inhibit = nengo.Ensemble(20,
                                     dimensions=1,
                                     intercepts=i_intercepts,
                                     encoders=Choice([[1]]))
        nengo.Connection(net.inhibit.neurons,
                         net.osc.neurons,
                         transform=-np.ones((n_per_d * 2, 20)))

        # --- Disinhibit when appropriate
        net.disinhibit = nengo.Node(size_in=1)
        nengo.Connection(net.disinhibit, net.inhibit, transform=-1)
    return net
Exemple #4
0
    def make_thresh_ens_net(self,
                            threshold=0.5,
                            thresh_func=lambda x: 1,
                            exp_scale=None,
                            num_ens=1,
                            net=None,
                            **args):
        if net is None:
            label_str = args.get('label', 'Threshold_Ens_Net')
            net = nengo.Network(label=label_str)
        if exp_scale is None:
            exp_scale = (1 - threshold) / 10.0

        with net:
            ens_args = dict(args)
            ens_args['n_neurons'] = args.get('n_neurons', self.n_neurons_ens)
            ens_args['dimensions'] = args.get('dimensions', 1)
            ens_args['intercepts'] = \
                Exponential(scale=exp_scale, shift=threshold,
                            high=1)
            ens_args['encoders'] = Choice([[1]])
            ens_args['eval_points'] = Uniform(min(threshold + 0.1, 1.0), 1.1)
            ens_args['n_eval_points'] = 5000

            net.input = nengo.Node(size_in=num_ens)
            net.output = nengo.Node(size_in=num_ens)

            for i in range(num_ens):
                thresh_ens = nengo.Ensemble(**ens_args)
                nengo.Connection(net.input[i], thresh_ens, synapse=None)
                nengo.Connection(thresh_ens,
                                 net.output[i],
                                 function=thresh_func,
                                 synapse=None)
        return net
Exemple #5
0
def make_mem_network(net, n_neurons, dimensions, make_mem_func, make_mem_args,
                     make_diff_func, make_diff_args, mem_synapse=0.1,
                     fdbk_transform=1.0, input_transform=1.0,
                     difference_gain=1.0, gate_gain=3):
    with net:
        net.input = nengo.Node(size_in=dimensions)

        # integrator to store value
        if np.isscalar(fdbk_transform):
            fdbk_matrix = np.eye(dimensions) * fdbk_transform
        else:
            fdbk_matrix = np.matrix(fdbk_transform)

        net.mem = make_mem_func(n_neurons=n_neurons, dimensions=dimensions,
                                label="mem", **make_mem_args)
        if isinstance(net.mem, nengo.Network):
            mem_output = net.mem.output
            mem_input = net.mem.input
        else:
            mem_output = mem_input = net.mem

        nengo.Connection(mem_output, mem_input,
                         synapse=mem_synapse, transform=fdbk_matrix)

        # calculate difference between stored value and input
        net.diff = make_diff_func(n_neurons=n_neurons, dimensions=dimensions,
                                  label="Diff", **make_diff_args)

        if isinstance(net.diff, nengo.Network):
            net.diff_input = net.diff.input
            diff_output = net.diff.output
        else:
            net.diff_input = diff_output = net.diff

        nengo.Connection(net.input, net.diff_input, synapse=None,
                         transform=net.input_transform)
        nengo.Connection(mem_output, net.diff_input, transform=-1)

        # feed difference into integrator
        nengo.Connection(diff_output, mem_input,
                         transform=difference_gain, synapse=mem_synapse)

        # gate difference (if gate==0, update stored value,
        # otherwise retain stored value)
        # Note: A node is used for the input to make reset circuit more
        #       straightforward
        net.gate = nengo.Ensemble(n_neurons, 1, encoders=Choice([[1]]),
                                  intercepts=Exponential(0.15, 0.5, 1),
                                  label='Gate')

        if isinstance(net.diff, nengo.Network):
            for e in net.diff.ensembles:
                nengo.Connection(net.gate, e.neurons,
                                 transform=[[-gate_gain]] * e.n_neurons)
        else:
            nengo.Connection(net.gate, net.diff.neurons,
                             transform=[[-gate_gain]] * e.n_neurons)

        # Make output
        net.output = net.mem.output
Exemple #6
0
def test_argreprs():
    def check_init_args(cls, args):
        assert getfullargspec(cls.__init__).args[1:] == args

    def check_repr(obj):
        assert eval(repr(obj)) == obj

    check_init_args(PDF, ['x', 'p'])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))

    check_init_args(Uniform, ['low', 'high', 'integer'])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))

    check_init_args(Gaussian, ['mean', 'std'])
    check_repr(Gaussian(0, 2))

    check_init_args(Exponential, ['scale', 'shift', 'high'])
    check_repr(Exponential(2.))
    check_repr(Exponential(2., shift=0.1))
    check_repr(Exponential(2., shift=0.1, high=10.))

    check_init_args(UniformHypersphere, ['surface', 'min_magnitude'])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))

    check_init_args(Choice, ['options', 'weights'])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))

    check_init_args(Samples, ['samples'])
    check_repr(Samples([3, 2, 1]))

    check_init_args(SqrtBeta, ['n', 'm'])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))

    check_init_args(SubvectorLength, ['dimensions', 'subdimensions'])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))

    check_init_args(CosineSimilarity, ['dimensions'])
    check_repr(CosineSimilarity(6))
Exemple #7
0
def test_argreprs():
    def check_init_args(cls, args):
        assert getfullargspec(cls.__init__).args[1:] == args

    def check_repr(obj):
        assert eval(repr(obj)) == obj

    check_init_args(PDF, ["x", "p"])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))

    check_init_args(Uniform, ["low", "high", "integer"])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))

    check_init_args(Gaussian, ["mean", "std"])
    check_repr(Gaussian(0, 2))

    check_init_args(Exponential, ["scale", "shift", "high"])
    check_repr(Exponential(2.0))
    check_repr(Exponential(2.0, shift=0.1))
    check_repr(Exponential(2.0, shift=0.1, high=10.0))

    check_init_args(UniformHypersphere, ["surface", "min_magnitude"])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))

    check_init_args(Choice, ["options", "weights"])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))

    check_init_args(Samples, ["samples"])
    check_repr(Samples([3, 2, 1]))

    check_init_args(SqrtBeta, ["n", "m"])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))

    check_init_args(SubvectorLength, ["dimensions", "subdimensions"])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))

    check_init_args(CosineSimilarity, ["dimensions"])
    check_repr(CosineSimilarity(6))
Exemple #8
0
 def default_ens_config(self):
     """(Config) Defaults for other ensemble creation."""
     cfg = nengo.Config(nengo.Ensemble)
     cfg[nengo.Ensemble].update({
         'radius': 1,
         'intercepts': Exponential(self.exp_scale, 0.0, 1.0),
         'encoders': Choice([[1]]),
         'eval_points': Uniform(0.0, 1.0),
         'n_eval_points': self.n_eval_points,
     })
     return cfg
Exemple #9
0
 def am_ens_config(self):
     """(Config) Defaults for associative memory ensemble creation."""
     cfg = nengo.Config(nengo.Ensemble, nengo.Connection)
     cfg[nengo.Ensemble].update({
         'radius': 1,
         'intercepts': Exponential(self.exp_scale, 0.0, 1.0),
         'encoders': Choice([[1]]),
         'eval_points': Uniform(0.0, 1.0),
         'n_eval_points': self.n_eval_points,
     })
     cfg[nengo.Connection].synapse = None
     return cfg
Exemple #10
0
    def build_classifier(self, net):
        intercepts = Exponential(0.15, self.classifier.reset_th, 1.0)
        net.classifier = nengo.Ensemble(20,
                                        dimensions=1,
                                        encoders=Choice([[1]]),
                                        neuron_type=nengo.AdaptiveLIF(),
                                        intercepts=intercepts)

        for dmp in net.syllables:
            transform = -self.classifier.inhib_scale * np.ones(
                (dmp.state.n_neurons, net.classifier.n_neurons))
            nengo.Connection(net.classifier.neurons,
                             dmp.state.neurons,
                             transform=transform,
                             synapse=0.01)
Exemple #11
0
 def default_ens_config(self):
     """(Config) Defaults for other ensemble creation."""
     cfg = Config(Ensemble)
     cfg[Ensemble].update({
         "radius":
         1,
         "intercepts":
         Exponential(self.exp_scale, 0.0, 1.0),
         "encoders":
         Choice([[1]]),
         "eval_points":
         Uniform(0.0, 1.0),
         "n_eval_points":
         self.n_eval_points,
     })
     return cfg
Exemple #12
0
 def am_ens_config(self):
     """(Config) Defaults for associative memory ensemble creation."""
     cfg = Config(Ensemble, Connection)
     cfg[Ensemble].update({
         "radius":
         1,
         "intercepts":
         Exponential(self.exp_scale, 0.0, 1.0),
         "encoders":
         Choice([[1]]),
         "eval_points":
         Uniform(0.0, 1.0),
         "n_eval_points":
         self.n_eval_points,
     })
     cfg[Connection].synapse = None
     return cfg
Exemple #13
0
def InverseDMP(n_per_d,
               forcing_f,
               scale=0.7,
               reset_scale=2.5,
               similarity_th=0.6,
               tau=0.05,
               net=None):
    if net is None:
        net = nengo.Network(label="Inverse Rhythmic DMP")

    obs_dims = forcing_f(0.).size
    state_dims = 1
    dims = state_dims + obs_dims

    with net:
        net.input = nengo.Node(size_in=obs_dims)

        # --- iDMP state contains system state and observations
        net.state = nengo.Ensemble(n_per_d * dims,
                                   dimensions=dims,
                                   n_eval_points=10000,
                                   radius=1.4)
        nengo.Connection(net.input, net.state[1:], synapse=None)

        # --- Update state based on the current observation
        f = ff_inv(forcing_f, thresh=similarity_th, scale=scale)
        nengo.Connection(net.state, net.state[0], function=f, synapse=tau)

        # --- Reset system state
        net.reset = nengo.Node(size_in=1)
        d_intercepts = Exponential(0.15, -0.5, 0.1)
        net.diff_inhib = nengo.Ensemble(20,
                                        dimensions=1,
                                        intercepts=d_intercepts,
                                        encoders=Choice([[1]]))
        net.diff = nengo.Ensemble(n_per_d, dimensions=1)
        nengo.Connection(net.reset, net.diff_inhib, transform=-1, synapse=None)
        nengo.Connection(net.diff_inhib.neurons,
                         net.diff.neurons,
                         transform=-np.ones((n_per_d, 20)))
        nengo.Connection(net.state[0], net.diff)
        nengo.Connection(net.diff, net.state[0], transform=-reset_scale)

    return net
Exemple #14
0
def DMP(n_per_d, c, forcing_f, tau=0.05, net=None):
    if net is None:
        net = nengo.Network(label="DMP")

    out_dims = forcing_f(0.).size
    with net:
        # --- Decode forcing_f from oscillator
        net.state = nengo.Ensemble(n_per_d,
                                   dimensions=1,
                                   label=forcing_f.__name__)
        nengo.Connection(net.state, net.state, synapse=tau)
        net.output = nengo.Node(size_in=out_dims)
        nengo.Connection(net.state,
                         net.output,
                         function=forcing_f,
                         synapse=None)

        # --- Input is a small biased oscillator to ramp up smoothly
        net.osc = nengo.Ensemble(n_per_d * 2, dimensions=2, radius=0.01)
        nengo.Connection(net.osc,
                         net.osc,
                         transform=np.array([[2, -1], [1, 2]]))  # actually?
        nengo.Connection(net.osc,
                         net.state,
                         transform=c,
                         function=lambda x: x[0] + 0.5)
        # Kick start the oscillator
        kick = nengo.Node(lambda t: 1 if t < 0.1 else 0)
        nengo.Connection(kick, net.osc, transform=np.ones((2, 1)))

        # --- Inhibit the state by default
        i_intercepts = Exponential(0.15, -0.5, 0.1)
        net.inhibit = nengo.Ensemble(20,
                                     dimensions=1,
                                     intercepts=i_intercepts,
                                     encoders=Choice([[1]]))
        nengo.Connection(net.inhibit.neurons,
                         net.state.neurons,
                         transform=-np.ones((n_per_d, 20)))

        # --- Disinhibit when appropriate
        net.disinhibit = nengo.Node(size_in=1)
        nengo.Connection(net.disinhibit, net.inhibit, transform=-1)
    return net
Exemple #15
0
def ThresholdingEnsembles(threshold, intercept_width=0.15, radius=1.0):
    """Configuration preset for a thresholding ensemble.

    This preset adjust ensemble parameters for thresholding. The ensemble's
    neurons will only fire for values above threshold. One can either decode
    the represented value (if it is above the threshold) or decode
    a step function if binary classification is desired.

    This preset:

    - Sets intercepts to be between ``threshold`` and ``radius`` with an
      exponential distribution (shape parameter of ``intercept_width``).
      This clusters intercepts near the threshold for better approximation.
    - Sets encoders to 1.
    - Sets evaluation points to be uniformly distributed between
      ``threshold`` and ``radius``.
    - Sets the radius.

    Parameters
    ----------
    threshold : float
        Point at which ensembles should start firing.
    intercept_width : float, optional
        Controls how widely distributed the intercepts are. Smaller values
        give more clustering at the threshold, larger values give a more
        uniform distribution.
    radius : float, optional
        Ensemble radius.

    Returns
    -------
    `nengo.Config`
        Configuration with presets.
    """
    config = Config(Ensemble)
    config[Ensemble].radius = radius
    config[Ensemble].intercepts = Exponential(intercept_width, threshold,
                                              radius)
    config[Ensemble].encoders = Choice([[1]])
    config[Ensemble].eval_points = Uniform(threshold / radius, 1)
    return config
Exemple #16
0
    def build_syllables(self, net):
        assert len(self.syllables) > 0, "No syllables added"

        # Make a readout for the production info coming from the DMPs
        intercepts = Exponential(0.15, self.production_info.threshold, 1)
        net.production_info = EnsembleArray(self.production_info.n_per_d,
                                            n_ensembles=48,
                                            encoders=Choice([[1]]),
                                            intercepts=intercepts,
                                            radius=1.1)

        net.syllables = []
        dt = self.trial.dt
        for syllable in self.syllables:
            forcing_f, gesture_ix = traj2func(syllable.trajectory, dt=dt)
            forcing_f.__name__ = syllable.label
            dmp = RhythmicDMP(forcing_f=forcing_f,
                              freq=syllable.freq,
                              **self.syllable.kwargs())
            nengo.Connection(dmp.output, net.production_info.input[gesture_ix])
            net.syllables.append(dmp)
Exemple #17
0
def DeadzoneDMP(n_per_d,
                freq,
                forcing_f,
                tau=0.025,
                deadzone=0.6 * np.pi,
                net=None):
    if net is None:
        net = nengo.Network(label="Rhythmic DMP")

    out_dims = forcing_f(0.).size
    omega = freq * tau * 2 * np.pi
    theta = UniformWithDeadzone(deadzone=deadzone).sample(n_per_d * 2, 1)
    encoders = np.hstack([np.cos(theta), np.sin(theta)])
    with net:
        # --- Decode forcing_f from oscillator
        net.osc = nengo.Ensemble(n_per_d * 2,
                                 dimensions=2,
                                 intercepts=Exponential(0.15, 0.3, 0.6),
                                 encoders=encoders,
                                 label=forcing_f.__name__)
        nengo.Connection(net.osc,
                         net.osc,
                         synapse=tau,
                         function=zone(deadzone),
                         transform=[[1, -omega], [omega, 1]])
        net.output = nengo.Node(size_in=out_dims)
        nengo.Connection(net.osc,
                         net.output,
                         function=radial_f(forcing_f, deadzone),
                         synapse=None)

        # --- Kick start the oscillator
        net.kick = nengo.Node(size_in=1)
        nengo.Connection(net.kick,
                         net.osc,
                         transform=[[-1], [0.05]],
                         synapse=None)
    return net
Exemple #18
0
def Sequencer(n_per_d, timer_tau=0.05, timer_freq=2.,
              reset_time=0.7, reset_threshold=0.5, reset_to_gate=-0.7,
              gate_threshold=0.4, net=None):
    if net is None:
        net = nengo.Network(label="Syllable sequencer")

    omega = timer_freq * timer_tau * 2 * np.pi

    with net:
        # --- Aggregate all the syllable DMPs to keep track of time
        net.timer = nengo.Ensemble(n_per_d * 2, dimensions=2)

        # --- Reset all DMPs at the right time
        r_intercepts = Exponential(0.15, reset_threshold, 1)
        net.reset = nengo.Ensemble(60, dimensions=1,
                                   encoders=Choice([[1]]),
                                   intercepts=r_intercepts)

        def reset_f(x):
            if x > reset_time:
                return 1.
            elif x < 0.05:
                return 0.8
            else:
                return 0
        nengo.Connection(net.timer, net.reset, function=radial_f(reset_f))

        # There's a catch 22 here. The reset forces the DMPs to a specific
        # point in state space, but that space is also where the timer starts
        # resetting DMPs. If we do nothing, then the DMPs will just stop.
        # To keep things moving, when the reset is active, we allow the
        # timer to oscillate on its own, rather than just using DMP input.

        # --- Make `timer` oscillate when reset is active
        net.timer_recur = nengo.Ensemble(n_per_d * 2, dimensions=2)
        nengo.Connection(net.timer, net.timer_recur)
        nengo.Connection(net.timer_recur, net.timer,
                         synapse=timer_tau,
                         transform=[[1, -omega], [omega, 1]])
        # Usually, the recurrent ensemble is inhibited
        inh_intercepts = Exponential(0.15, -0.5, 0.1)
        net.tr_inhibit = nengo.Ensemble(20, dimensions=1,
                                        encoders=Choice([[1]]),
                                        intercepts=inh_intercepts)
        nengo.Connection(net.tr_inhibit.neurons, net.timer_recur.neurons,
                         transform=-np.ones((n_per_d * 2, 20)))
        # But the reset disinhibits the recurrence
        nengo.Connection(net.reset, net.tr_inhibit, transform=-1)

        # --- `gate` switches the working memory representations
        g_intercepts = Exponential(0.15, gate_threshold, 1)
        net.gate = nengo.Ensemble(60, dimensions=1,
                                  encoders=Choice([[1]]),
                                  intercepts=g_intercepts)
        # Gate is normally always active
        net.gate_bias = nengo.Node(output=1)
        nengo.Connection(net.gate_bias, net.gate, synapse=None)
        # Reset inhibits gate, causing switch to next syllable
        nengo.Connection(net.reset, net.gate, transform=reset_to_gate)

    return net
Exemple #19
0
    def init_module(self):
        bias_node = nengo.Node(output=1)

        # ---------------------- Inputs and outputs ------------------------- #
        # Motor SP input node
        self.motor_sp_in = nengo.Node(size_in=vocab.mtr_dim)

        # Motor bypass signal (runs the ramp, but doesn't output to the arm)
        self.motor_bypass = cfg.make_thresh_ens_net()

        # Motor init signal
        self.motor_init_vis = cfg.make_thresh_ens_net(0.75, n_neurons=100)
        self.motor_init_ps_task = cfg.make_thresh_ens_net(0.75, n_neurons=100)
        self.motor_init_ps_dec = cfg.make_thresh_ens_net(0.75, n_neurons=100)

        # --------------- MOTOR SIGNALLING SYSTEM (STOP / GO) --------------
        # Motor go signal
        self.motor_go = nengo.Ensemble(cfg.n_neurons_ens, 1)
        nengo.Connection(bias_node, self.motor_go)

        # Motor stop signal
        self.motor_stop_input = cfg.make_thresh_ens_net()
        nengo.Connection(bias_node, self.motor_stop_input.input, synapse=None)
        nengo.Connection(self.motor_stop_input.output,
                         self.motor_go.neurons,
                         transform=[[-3]] * cfg.n_neurons_ens)

        # --------------- MOTOR SIGNALLING SYSTEM (RAMP SIG) --------------
        self.ramp_sig = Ramp_Signal_Network()

        # Signal used to drive the ramp (the constant input signal)
        nengo.Connection(self.motor_go,
                         self.ramp_sig.ramp,
                         transform=cfg.mtr_ramp_synapse * cfg.mtr_ramp_scale,
                         synapse=cfg.mtr_ramp_synapse)

        # Signal to hold the ramp reset as long as the motor system is still
        # initializing (e.g. arm is still going to INIT target)
        # nengo.Connection(self.motor_init.output, self.ramp_sig.init,
        #                  transform=1.75, synapse=0.015)
        nengo.Connection(self.motor_init_vis.output,
                         self.ramp_sig.init,
                         transform=3,
                         synapse=0.008)
        # nengo.Connection(self.motor_init_vis.output, self.ramp_sig.init,
        #                  transform=-6, synapse=0.05)
        nengo.Connection(self.motor_init_ps_task.output,
                         self.ramp_sig.init,
                         transform=5,
                         synapse=0.008)
        nengo.Connection(self.motor_init_ps_task.output,
                         self.ramp_sig.init,
                         transform=-6.5,
                         synapse=0.05)
        nengo.Connection(self.motor_init_ps_dec.output,
                         self.ramp_sig.init,
                         transform=5,
                         synapse=0.008)
        nengo.Connection(self.motor_init_ps_dec.output,
                         self.ramp_sig.init,
                         transform=-6.5,
                         synapse=0.05)

        # Stop the ramp from starting if the stop command has been given
        nengo.Connection(self.motor_stop_input.output,
                         self.ramp_sig.go,
                         transform=-1)

        # --------------- FUNCTION REPLICATOR SYSTEM --------------
        mtr_func_dim = vocab.mtr_dim // 2
        func_eval_net = DiffFuncEvaltr(mtr_func_dim,
                                       mtr_data.sp_scaling_factor, 2)
        func_eval_net.make_inhibitable(-5)

        nengo.Connection(self.ramp_sig.ramp, func_eval_net.func_input)
        nengo.Connection(self.motor_bypass.output, func_eval_net.inhibit)

        # Motor path x information - Note conversion to difference of points
        # from path of points
        nengo.Connection(self.motor_sp_in[:mtr_func_dim],
                         func_eval_net.diff_func_pts[0])
        nengo.Connection(self.motor_sp_in[:mtr_func_dim - 1],
                         func_eval_net.diff_func_pts[0][1:],
                         transform=-1)
        # Motor path y information - Note conversion to difference of points
        # from path of points
        nengo.Connection(self.motor_sp_in[mtr_func_dim:],
                         func_eval_net.diff_func_pts[1])
        nengo.Connection(self.motor_sp_in[mtr_func_dim:-1],
                         func_eval_net.diff_func_pts[1][1:],
                         transform=-1)

        # --------------- MOTOR ARM CONTROL -----------------
        arm_obj = cfg.mtr_arm_class()

        if arm_obj is not None:
            arm_rest_coord = np.array(
                arm_obj.position(q=arm_obj.rest_angles, ee_only=True))
            # Note: arm_rest_coord is only used for initialization & startup
            #       transients
            arm_node = nengo.Node(output=lambda t, x, dt=cfg.sim_dt, arm=
                                  arm_obj: arm.apply_torque(x, dt),
                                  size_in=arm_obj.DOF)

            kp = mtr_data.kp if cfg.mtr_kp is None else cfg.mtr_kp
            kv1 = mtr_data.kv1 if cfg.mtr_kv1 is None else cfg.mtr_kv1
            kv2 = mtr_data.kv2 if cfg.mtr_kv2 is None else cfg.mtr_kv2

            ctrl_obj = Controller(dt=cfg.sim_dt,
                                  arm=arm_obj,
                                  kp=kp,
                                  kv=kv1,
                                  kv2=kv2,
                                  init_target=arm_rest_coord,
                                  arm_class_name=cfg.mtr_arm_type)

            # Make the osc control
            ctrl_net = ctrl_obj.initialize_model()
            self.ctrl_net = ctrl_net

            # Connect output of motor path evaluator to ctrl_net
            nengo.Connection(func_eval_net.func_output,
                             ctrl_net.target,
                             synapse=0.01)

            # Add bias values to the motor path evaluator output (to shift the
            # drawn digit into the drawing box of the arm)
            nengo.Connection(bias_node,
                             ctrl_net.target,
                             transform=[[cfg.mtr_arm_rest_x_bias],
                                        [cfg.mtr_arm_rest_y_bias]],
                             synapse=None)

            # Feed the torque control signal to the arm
            nengo.Connection(ctrl_net.output, arm_node)

            if cfg.mtr_dyn_adaptation:
                # Arm state
                arm_state = nengo.Node(
                    output=lambda t, arm=arm_obj: np.hstack([arm.q, arm.dq]))

                # Create ensemble for arm dynamics adaptation
                adapt_ens = nengo.Ensemble(cfg.mtr_dyn_adaptation_n_neurons,
                                           arm_obj.DOF * 2)

                # Get information from the arm and connect to learning ensemble
                nengo.Connection(
                    arm_state,
                    adapt_ens,
                    function=lambda x: ctrl_obj.config.CB_scaledown(x))

                # Make the learning connection
                adapt_conn = nengo.Connection(
                    adapt_ens,
                    arm_node,
                    function=lambda x: [0, 0, 0],
                    learning_rule_type=nengo.PES(
                        cfg.mtr_dyn_adaptation_learning_rate),
                    synapse=cfg.mtr_dyn_adaptation_synapse)
                nengo.Connection(ctrl_net.output,
                                 adapt_conn.learning_rule,
                                 transform=-1)

                self.adapt_conn = adapt_conn
                self.adapt_ens = adapt_ens

            # ------ MOTOR ARM FORCE FIELD ADDITION ------
            forcefield_obj = getattr(forcefield, cfg.mtr_forcefield)(arm_obj)
            forcefield_node = nengo.Node(
                size_in=arm_obj.DOF,
                output=lambda t, x: forcefield_obj.generate(x))
            nengo.Connection(ctrl_net.output, forcefield_node, synapse=None)
            nengo.Connection(forcefield_node,
                             arm_node,
                             synapse=cfg.mtr_forcefield_synapse)

            self.ff_node = forcefield_node

            # ------ ARM ZERO-CENTERED END EFFECTOR POSITION ------
            # ## Note: ctrl_net already has an internal node that gets info
            #          from arm_obj (i.e. state information). So an external
            #          connection is not required

            zero_centered_arm_ee_loc = \
                nengo.Node(output=lambda t,
                           bias=np.array([cfg.mtr_arm_rest_x_bias,
                                          cfg.mtr_arm_rest_y_bias]),
                           arm=arm_obj: arm.x - bias, label='Centered Arm EE')

        # ------ MOTOR ARM CONTROL SIGNAL FEEDBACK ------
        # X to target norm calculation
        target_thresh = cfg.mtr_tgt_threshold
        target_diff_norm = \
            nengo.Ensemble(150, 2,
                           intercepts=Exponential(0.09, target_thresh,
                                                  target_thresh * 2),
                           radius=target_thresh * 2)

        nengo.Connection(func_eval_net.func_output,
                         target_diff_norm,
                         synapse=0.01)
        if arm_obj is not None:
            nengo.Connection(zero_centered_arm_ee_loc,
                             target_diff_norm,
                             transform=-1,
                             synapse=0.01)
        else:
            nengo.Connection(func_eval_net.func_output,
                             target_diff_norm,
                             synapse=0.01)

        target_diff_norm_thresh = cfg.make_thresh_ens_net()
        nengo.Connection(target_diff_norm,
                         target_diff_norm_thresh.input,
                         function=lambda x: (np.sqrt(x[0]**2 + x[1]**2)) > 0,
                         transform=2)

        # When the target != arm ee position, stop the ramp signal from
        # starting (reaching to start position)
        # nengo.Connection(target_diff_norm, self.ramp_sig.go, transform=-6,
        #                  function=lambda x:
        #                  (np.sqrt(x[0] ** 2 + x[1] ** 2)) > 0,
        #                  synapse=0.01)
        nengo.Connection(target_diff_norm_thresh.output,
                         self.ramp_sig.go,
                         transform=-2,
                         synapse=0.01)
        # When the target != arm ee position, stop the ramp signal from
        # stopping (reaching to end position)
        # nengo.Connection(target_diff_norm, self.ramp_sig.end,
        #                  transform=-8,
        #                  function=lambda x:
        #                  (np.sqrt(x[0] ** 2 + x[1] ** 2)) > 0,
        #                  synapse=0.01)
        nengo.Connection(target_diff_norm_thresh.output,
                         self.ramp_sig.end,
                         transform=-2,
                         synapse=0.01)

        # Disable the target_diff_norm when motor bypass
        nengo.Connection(self.motor_bypass.output,
                         target_diff_norm.neurons,
                         transform=[[-10.0]] * target_diff_norm.n_neurons,
                         synapse=0.01)
        if arm_obj is None:
            # Disable the target_diff_norm when there is no arm object
            nengo.Connection(bias_node,
                             target_diff_norm.neurons,
                             transform=[[-10.0]] * target_diff_norm.n_neurons,
                             synapse=0.01)

        # ------ MOTOR PEN DOWN CONTROL ------
        pen_down = cfg.make_thresh_ens_net()

        # Pen is down by default
        nengo.Connection(bias_node, pen_down.input)

        # Cases when the pen should NOT be down
        nengo.Connection(self.ramp_sig.reset_hold,
                         pen_down.input,
                         transform=-1)
        nengo.Connection(self.ramp_sig.stop, pen_down.input, transform=-1)
        nengo.Connection(self.motor_stop_input.output,
                         pen_down.input,
                         transform=-1,
                         synapse=0.05)
        nengo.Connection(self.motor_bypass.output,
                         pen_down.input,
                         transform=-1)

        # Pen down signal feedback to rest of motor system (tells the ramp to
        # keep going, and the ctrl_net to use only kv1)
        nengo.Connection(pen_down.output, self.ramp_sig.go, transform=12)
        if arm_obj is not None:
            nengo.Connection(pen_down.output, ctrl_net.CB2_inhibit)

        # --------------- For external probes ---------------
        self.ramp_int_stop = self.ramp_sig.stop

        # Motor target output
        self.mtr_path_func_out = nengo.Node(size_in=2)
        nengo.Connection(func_eval_net.diff_func_outputs[0],
                         self.mtr_path_func_out[0],
                         transform=np.ones((1, mtr_func_dim)))
        nengo.Connection(func_eval_net.diff_func_outputs[1],
                         self.mtr_path_func_out[1],
                         transform=np.ones((1, mtr_func_dim)))

        # Arm segments joint locations
        if arm_obj is not None:
            self.arm_px_node = \
                nengo.Node(output=lambda t, arm=arm_obj: arm.position()[0])
            self.arm_py_node = \
                nengo.Node(output=lambda t, arm=arm_obj: arm.position()[1])
        else:
            self.arm_px_node = nengo.Node(0)
            self.arm_py_node = nengo.Node(0)

        # Arm ee zero_centered location
        if arm_obj is not None:
            self.zero_centered_arm_ee_loc = zero_centered_arm_ee_loc

        # Target ee zero_centered location
        self.zero_centered_tgt_ee_loc = func_eval_net.func_output

        # Pen down status
        self.pen_down = pen_down.output

        # Ramp signal outputs
        self.ramp = self.ramp_sig.ramp
        self.ramp_init_hold = self.ramp_sig.init_hold
        self.ramp_reset_hold = self.ramp_sig.reset_hold
        self.ramp_50_75 = self.ramp_sig.ramp_50_75

        # Decode index (number) bypass to monitor module
        self.dec_ind = nengo.Node(size_in=len(vocab.mtr.keys) + 1)

        # Target diff norm
        # self.target_diff_norm_out = nengo.Node(size_in=1)
        # nengo.Connection(target_diff_norm, self.target_diff_norm_out,
        #                  transform=-6,
        #                  function=lambda x:
        #                  (np.sqrt(x[0] ** 2 + x[1] ** 2)) > 0,
        #                  synapse=0.01)
        self.target_diff_norm_out = target_diff_norm_thresh.output

        # ################ DEBUG CODE ###################
        # motor_init signal
        self.motor_init = nengo.Node(size_in=1)
        # nengo.Connection(self.motor_init_vis.output, self.motor_init)
        # nengo.Connection(self.motor_init_ps_task.output, self.motor_init)
        # nengo.Connection(self.motor_init_ps_dec.output, self.motor_init)
        nengo.Connection(self.motor_init_vis.output,
                         self.motor_init,
                         transform=3,
                         synapse=0.0035)
        nengo.Connection(self.motor_init_ps_task.output,
                         self.motor_init,
                         transform=5,
                         synapse=0.0035)
        nengo.Connection(self.motor_init_ps_task.output,
                         self.motor_init,
                         transform=-6,
                         synapse=0.05)
        nengo.Connection(self.motor_init_ps_dec.output,
                         self.motor_init,
                         transform=5,
                         synapse=0.0035)
        nengo.Connection(self.motor_init_ps_dec.output,
                         self.motor_init,
                         transform=-6,
                         synapse=0.05)

        self.arm_state = nengo.Node(
            output=lambda t, arm=arm_obj: np.hstack([arm.q, arm.dq]))
        self.arm_dq = nengo.Node(output=lambda t, arm=arm_obj: arm.dq)
Exemple #20
0
def make_route_connections_common(net, n_neurons, dimensions, num_items,
                                  make_ens_func, gate_gain, default_sel,
                                  threshold_sel_in, **ens_args):
    with net:
        bias_node = nengo.Node(output=1)

        net.sel_none = nengo.Ensemble(20, 1)
        nengo.Connection(bias_node, net.sel_none, synapse=None)

        for n in range(num_items):
            sel_node = nengo.Node(size_in=1)
            sel_in = sel_node
            ens = make_ens_func(n_neurons=n_neurons,
                                dimensions=dimensions,
                                label='Gate %d' % n,
                                **ens_args)

            if threshold_sel_in:
                sel_node = nengo.Ensemble(50,
                                          1,
                                          intercepts=Exponential(
                                              0.05, 0.25, 0.5),
                                          encoders=Choice([[1]]),
                                          label='Sel In %d' % n)
                nengo.Connection(sel_in, sel_node, synapse=None)

            nengo.Connection(sel_node,
                             net.sel_none.neurons,
                             transform=([[-gate_gain]] *
                                        net.sel_none.n_neurons))

            if isinstance(ens, nengo.Network):
                if n != default_sel:
                    for e in ens.all_ensembles:
                        nengo.Connection(net.sel_none,
                                         e.neurons,
                                         transform=[[-gate_gain]] *
                                         e.n_neurons)
                for sn in net.sel_nodes:
                    for e in ens.all_ensembles:
                        nengo.Connection(sn,
                                         e.neurons,
                                         transform=[[-gate_gain]] *
                                         e.n_neurons)
                for ee in net.ens_elements:
                    for e in ee.all_ensembles:
                        nengo.Connection(sel_node,
                                         e.neurons,
                                         transform=[[-gate_gain]] *
                                         e.n_neurons)
            else:
                if n != default_sel:
                    nengo.Connection(net.sel_none,
                                     ens.neurons,
                                     transform=[[-gate_gain]] * ens.n_neurons)
                for sn in net.sel_nodes:
                    nengo.Connection(sn,
                                     ens.neurons,
                                     transform=[[-gate_gain]] * ens.n_neurons)
                for ee in net.ens_elements:
                    nengo.Connection(sel_node,
                                     ee.neurons,
                                     transform=[[-gate_gain]] * ee.n_neurons)

            net.ens_elements.append(ens)
            net.sel_nodes.append(sel_node)

            setattr(net, 'sel%i' % n, sel_in)
            setattr(net, 'ens%i' % n, ens)
Exemple #21
0
    def __init__(self,
                 n_neurons,
                 dimensions,
                 vocab,
                 radius=None,
                 gate_mode=1,
                 reset_mode=3,
                 cleanup_mode=0,
                 cleanup_keys=None,
                 reset_key=None,
                 threshold_gate_in=False,
                 gate_threshold=0.5,
                 label=None,
                 seed=None,
                 add_to_container=None,
                 **mem_args):
        super(MemoryBlock, self).__init__(label, seed, add_to_container)

        if radius is None:
            radius = 3.5 / np.sqrt(dimensions)

        if n_neurons == nengo.Default:
            n_neurons = 100

        if cleanup_keys is not None:
            cleanup_vecs = vocab.create_subset(cleanup_keys).vectors
        elif cleanup_mode != 0:
            cleanup_vecs = vocab.vectors
        else:
            cleanup_vecs = None

        if isinstance(reset_key, str):
            reset_vec = vocab.parse(reset_key).v
        elif (not isinstance(reset_key, (np.ndarray, np.generic))
              and reset_key is not None and reset_key != 0):
            reset_vec = np.ones(dimensions) * reset_key
        else:
            reset_vec = reset_key

        if reset_key is None:
            reset_mode = 0

        with self:
            # cleanup_mode:
            # - 0 (or cleanup_vecs == None): No cleanup
            # - 1: Cleanup memory vectors using provided vectors. Only store
            #      vectors that can be cleaned up.
            # - 2: Cleanup memory vectors using provided vectors but also allow
            #      vectors that do not match any of the cleanup vectors to be
            #      stored as well.
            wm_args = dict(mem_args)
            if cleanup_vecs is None or cleanup_mode == 0:
                self.mem1 = WM(n_neurons,
                               dimensions,
                               radius=radius,
                               reset_value=reset_vec,
                               **wm_args)
                wm_args.pop('input_transform', None)
                wm_args.pop('wta_output', None)
                self.mem2 = WM(n_neurons,
                               dimensions,
                               radius=radius,
                               reset_value=reset_vec,
                               **wm_args)
            elif cleanup_mode == 1:
                self.mem1 = WMC(n_neurons,
                                dimensions,
                                radius=radius,
                                cleanup_values=cleanup_vecs,
                                reset_value=reset_vec,
                                **wm_args)
                wm_args.pop('input_transform', None)
                wm_args.pop('wta_output', None)
                self.mem2 = WMC(n_neurons,
                                dimensions,
                                radius=radius,
                                cleanup_values=cleanup_vecs,
                                reset_value=reset_vec,
                                **wm_args)
            else:
                self.mem1 = WMCP(n_neurons,
                                 dimensions,
                                 radius=radius,
                                 cleanup_values=cleanup_vecs,
                                 reset_value=reset_vec,
                                 **wm_args)
                wm_args.pop('input_transform', None)
                wm_args.pop('wta_output', None)
                self.mem2 = WMCP(n_neurons,
                                 dimensions,
                                 radius=radius,
                                 cleanup_values=cleanup_vecs,
                                 reset_value=reset_vec,
                                 **wm_args)

            # Create gating threshold ensembles if needed. Note that the these
            # are needed if the WM network does not have its own gating
            # threshold population. The gating signal needs to be dead-zero
            # (no neural activity) when WM is non-gated.
            if threshold_gate_in:
                gate1 = nengo.Ensemble(n_neurons,
                                       1,
                                       label="gate1",
                                       intercepts=Exponential(0.15, 0.5, 1),
                                       encoders=Choice([[1]]))
                nengo.Connection(gate1, self.mem1.gate)

                gate2 = nengo.Ensemble(n_neurons,
                                       1,
                                       label="gate2",
                                       intercepts=Exponential(0.15, 0.5, 1),
                                       encoders=Choice([[1]]))
                nengo.Connection(gate2, self.mem2.gate)
            else:
                gate1 = self.mem1.gate
                gate2 = self.mem2.gate

            # Gate_modes:
            # - 1: Gate mem1 on gate high, gate mem2 on gate low (default)
            # - 2: Gate mem1 on gate low, gate mem2 on gate high
            if gate_mode == 1:
                self.gateX = gate1
                self.gateN = gate2
            else:
                self.gateX = gate2
                self.gateN = gate1

            self.gate = nengo.Node(size_in=1, label="gate")
            bias_node = nengo.Node(output=1)

            # Adjust gate thresholds
            nengo.Connection(bias_node,
                             self.gateX,
                             transform=0.5 - gate_threshold)
            nengo.Connection(bias_node,
                             self.gateN,
                             transform=gate_threshold - 0.5)

            nengo.Connection(self.gate, self.gateX)
            nengo.Connection(self.gate, self.gateN, transform=-1)
            nengo.Connection(bias_node, self.gateN)

            # Reset_modes:
            # - 1: Reset only mem1
            # - 2: Reset only mem2
            # - 3: Reset both mem1 and mem2
            if reset_mode:
                self.reset = \
                    nengo.Ensemble(n_neurons, 1, label="reset",
                                   intercepts=Exponential(0.15, 0.5, 1),
                                   encoders=Choice([[1]]))
            if reset_mode & 1:
                nengo.Connection(self.reset, self.mem1.reset, synapse=0.005)
            if reset_mode & 2:
                nengo.Connection(self.reset, self.mem2.reset, synapse=0.005)

            nengo.Connection(self.mem1.output, self.mem2.input, synapse=0.005)

        # Input and output nodes
        self.input = self.mem1.input
        self.output = self.mem2.output

        # Configure SPA default input and output vocabularies
        self.inputs = dict(default=(self.input, vocab))
        self.outputs = dict(default=(self.output, vocab))
Exemple #22
0
def make_resettable(net,
                    n_neurons,
                    dimensions,
                    reset_value,
                    make_reset_func,
                    make_reset_args,
                    gate_gain=3):
    # Why have all this extra hardware to reset WM when inhibition will do
    # it?
    # - Makes the reset more reliable (storing a zero, rather than just
    #   wiping it out), so that reset signal can be shorter.
    if np.isscalar(reset_value):
        reset_value = np.matrix(np.ones(dimensions) * reset_value)
    else:
        reset_value = np.matrix(reset_value)

    with net:
        bias = nengo.Node(output=1, label='bias')
        net.reset = nengo.Node(size_in=1, label='reset')

        # Create resetX and resetN signals. resetX is to disable the WM gate
        # signal when reset is high. resetN is to disable the reset circuitry
        # when reset is low.
        resetX = nengo.Ensemble(n_neurons,
                                1,
                                encoders=Choice([[1]]),
                                intercepts=Exponential(0.15, 0.5, 1),
                                label='ResetX')
        resetN = nengo.Ensemble(n_neurons,
                                1,
                                encoders=Choice([[1]]),
                                intercepts=Exponential(0.15, 0.75, 1),
                                label='ResetN')
        resetN_delay = nengo.Ensemble(n_neurons,
                                      1,
                                      encoders=Choice([[1]]),
                                      intercepts=Exponential(0.15, 0.75, 1),
                                      label='ResetN delay')

        nengo.Connection(net.reset, resetX, synapse=None)
        # nengo.Connection(net.reset, resetN, transform=-1, synapse=None)
        nengo.Connection(resetX, resetN, transform=-gate_gain)
        # Note: gate_gain transform is to match net.gate -- so that the 'turn
        #       off' time is identical to net.gate
        nengo.Connection(bias, resetN, synapse=None)
        nengo.Connection(resetN, resetN_delay, synapse=0.01)

        # THe reset gate. Controls reset information going into the difference
        # population
        reset_gate = make_reset_func(n_neurons=n_neurons,
                                     dimensions=dimensions,
                                     label="Reset gate",
                                     **make_reset_args)

        if isinstance(reset_gate, nengo.Network):
            reset_gate_input = reset_gate.input
            reset_gate_output = reset_gate.output
        else:
            reset_gate_input = reset_gate_output = reset_gate

        # The desired reset value.
        nengo.Connection(bias,
                         reset_gate_input,
                         transform=reset_value.T,
                         synapse=None)
        # Need to negate whatever is being fed to the input of the WM (since
        # the WM difference population is going to be enabled).
        nengo.Connection(net.input,
                         reset_gate_input,
                         transform=-net.input_transform,
                         synapse=None)

        nengo.Connection(reset_gate_output, net.diff_input)
        # Note: Synapse is there to give slight delay for reset signal (to
        # gate) to dissipate.

        # Enable the WM difference population
        nengo.Connection(resetX, net.gate, transform=-gate_gain)

        # Disable the reset gate when reset signal is not active.
        if isinstance(reset_gate, nengo.Network):
            for e in reset_gate.ensembles:
                nengo.Connection(resetN_delay,
                                 e.neurons,
                                 transform=[[-gate_gain]] * e.n_neurons)
        else:
            nengo.Connection(resetN_delay,
                             reset_gate.neurons,
                             transform=[[-gate_gain]] * e.n_neurons)
Exemple #23
0
    def init_module(self):
        bias_node = nengo.Node(1)

        # Number of actions in this spaun setup
        num_actions = experiment.num_learn_actions

        # ------------------- Action detection network ------------------------
        # Translates
        self.action_input = nengo.Node(size_in=num_actions)
        self.bg_utilities_input = nengo.Node(size_in=num_actions)
        self.vis_sp_input = nengo.Node(size_in=vocab.sp_dim)

        # ------------------- Reward detection network ------------------------
        # Translates visual input into reward yes/no signals
        # Note: Output of reward_detect is inverted
        num_reward_sps = len(vocab.reward.keys)
        self.reward_detect = cfg.make_thresh_ens_net(num_ens=num_reward_sps)
        nengo.Connection(bias_node,
                         self.reward_detect.input,
                         transform=np.ones(num_reward_sps)[:, None])
        nengo.Connection(self.vis_sp_input,
                         self.reward_detect.input,
                         transform=-vocab.reward.vectors,
                         synapse=None)

        # Calculate positive reward values
        self.pos_reward_vals = \
            cfg.make_ens_array(n_ensembles=num_actions, radius=1)
        nengo.Connection(self.action_input,
                         self.pos_reward_vals.input,
                         transform=np.eye(num_actions),
                         synapse=None)

        # Calculate negative reward values
        self.neg_reward_vals = \
            cfg.make_ens_array(n_ensembles=num_actions, radius=1)
        nengo.Connection(self.action_input,
                         self.neg_reward_vals.input,
                         transform=np.ones(num_actions) - np.eye(num_actions),
                         synapse=None)

        # Do the appropriate reward cross linking
        for i in range(num_actions):
            # No reward detect --> disinhibit neg_reward_vals
            nengo.Connection(self.reward_detect.output[0],
                             self.neg_reward_vals.ensembles[i].neurons,
                             transform=[[-3]] *
                             self.neg_reward_vals.ensembles[i].n_neurons)
            # Yes reward detect --> disinhibit pos_reward_vals
            nengo.Connection(self.reward_detect.output[1],
                             self.pos_reward_vals.ensembles[i].neurons,
                             transform=[[-3]] *
                             self.pos_reward_vals.ensembles[i].n_neurons)

        # Calculate the utility bias needed (so that the rewards don't send
        # the utilities to +inf, -inf)
        self.util_vals = EnsembleArray(100,
                                       num_actions,
                                       encoders=Choice([[1]]),
                                       intercepts=Exponential(0.15, 0.3, 1))
        nengo.Connection(self.reward_detect.output,
                         self.util_vals.input,
                         transform=-np.ones((num_actions, 2)))
        nengo.Connection(self.action_input,
                         self.util_vals.input,
                         transform=np.ones((num_actions, num_actions)),
                         synapse=None)
        nengo.Connection(self.bg_utilities_input,
                         self.util_vals.input,
                         transform=1,
                         synapse=None)
Exemple #24
0
    def init_module(self):
        bias_node = nengo.Node(output=1)

        # ---------------------- Inputs and outputs ------------------------- #
        # Motor SP input node
        self.motor_sp_in = nengo.Node(size_in=vocab.mtr_dim)

        # Motor bypass signal (runs the ramp, but doesn't output to the arm)
        self.motor_bypass = cfg.make_thresh_ens_net()

        # Motor init signal
        self.motor_init = cfg.make_thresh_ens_net(0.75)

        # --------------- MOTOR SIGNALLING SYSTEM (STOP / GO) --------------
        # Motor go signal
        self.motor_go = nengo.Ensemble(cfg.n_neurons_ens, 1)
        nengo.Connection(bias_node, self.motor_go)

        # Motor stop signal
        self.motor_stop_input = cfg.make_thresh_ens_net()
        nengo.Connection(bias_node, self.motor_stop_input.input, synapse=None)
        nengo.Connection(self.motor_stop_input.output,
                         self.motor_go.neurons,
                         transform=[[-3]] * cfg.n_neurons_ens)

        # --------------- MOTOR SIGNALLING SYSTEM (RAMP SIG) --------------
        self.ramp_sig = Ramp_Signal_Network()

        # Signal used to drive the ramp (the constant input signal)
        nengo.Connection(self.motor_go,
                         self.ramp_sig.ramp,
                         transform=cfg.mtr_ramp_synapse * cfg.mtr_ramp_scale,
                         synapse=cfg.mtr_ramp_synapse)

        # Signal to hold the ramp reset as long as the motor system is still
        # initializing (e.g. arm is still going to INIT target)
        nengo.Connection(self.motor_init.output,
                         self.ramp_sig.init,
                         transform=1.75,
                         synapse=0.015)

        # Stop the ramp from starting if the stop command has been given
        nengo.Connection(self.motor_stop_input.output,
                         self.ramp_sig.go,
                         transform=-1)

        # --------------- FUNCTION REPLICATOR SYSTEM --------------
        mtr_func_dim = vocab.mtr_dim // 2
        func_eval_net = DiffFuncEvaltr(mtr_func_dim,
                                       mtr_data.sp_scaling_factor, 2)
        func_eval_net.make_inhibitable(-5)

        nengo.Connection(self.ramp_sig.ramp, func_eval_net.func_input)
        nengo.Connection(self.motor_bypass.output, func_eval_net.inhibit)

        # Motor path x information - Note conversion to difference of points
        # from path of points
        nengo.Connection(self.motor_sp_in[:mtr_func_dim],
                         func_eval_net.diff_func_pts[0])
        nengo.Connection(self.motor_sp_in[:mtr_func_dim - 1],
                         func_eval_net.diff_func_pts[0][1:],
                         transform=-1)
        # Motor path y information - Note conversion to difference of points
        # from path of points
        nengo.Connection(self.motor_sp_in[mtr_func_dim:],
                         func_eval_net.diff_func_pts[1])
        nengo.Connection(self.motor_sp_in[mtr_func_dim:-1],
                         func_eval_net.diff_func_pts[1][1:],
                         transform=-1)

        # --------------- MOTOR ARM CONTROL -----------------
        arm_obj = cfg.mtr_arm_class()

        if arm_obj is not None:
            arm_rest_coord = np.array(
                arm_obj.position(q=arm_obj.rest_angles, ee_only=True))
            # Note: arm_rest_coord is only used for initialization & startup
            #       transients
            arm_node = nengo.Node(
                output=lambda t, x, dt=cfg.sim_dt: arm_obj.apply_torque(x, dt),
                size_in=arm_obj.DOF)

            osc_obj = OSController(dt=cfg.sim_dt,
                                   arm=arm_obj,
                                   kp=cfg.mtr_kp,
                                   kv=cfg.mtr_kv1,
                                   kv2=cfg.mtr_kv2,
                                   init_target=arm_rest_coord)

            # Make the osc control
            osc_net = osc_obj.initialize_model()

            # Connect output of motor path evaluator to osc_net
            nengo.Connection(func_eval_net.func_output,
                             osc_net.target,
                             synapse=0.01)

            # Add bias values to the motor path evaluator output (to shift the
            # drawn digit into the drawing box of the arm)
            nengo.Connection(bias_node,
                             osc_net.target,
                             transform=[[cfg.mtr_arm_rest_x_bias],
                                        [cfg.mtr_arm_rest_y_bias]],
                             synapse=None)

            # Feed the torque control signal to the arm
            nengo.Connection(osc_net.output, arm_node)

            # ## Note: osc_net already has an internal node that gets info
            #          from arm_obj (i.e. state information). So an external
            #          connection is not required

            zero_centered_arm_ee_loc = \
                nengo.Node(output=lambda t,
                           bias=np.array([cfg.mtr_arm_rest_x_bias,
                                          cfg.mtr_arm_rest_y_bias]):
                           arm_obj.x - bias, label='Centered Arm EE')

        # ------ MOTOR ARM CONTROL SIGNAL FEEDBACK ------
        # X to target norm calculation
        target_thresh = cfg.mtr_tgt_threshold
        target_diff_norm = \
            nengo.Ensemble(150, 2,
                           intercepts=Exponential(0.05, target_thresh,
                                                  target_thresh * 2),
                           radius=target_thresh * 2)

        nengo.Connection(func_eval_net.func_output,
                         target_diff_norm,
                         synapse=0.01)
        if arm_obj is not None:
            nengo.Connection(zero_centered_arm_ee_loc,
                             target_diff_norm,
                             transform=-1,
                             synapse=0.01)
        else:
            nengo.Connection(func_eval_net.func_output,
                             target_diff_norm,
                             synapse=0.01)

        # When the target != arm ee position, stop the ramp signal from
        # starting (reaching to start position)
        nengo.Connection(target_diff_norm,
                         self.ramp_sig.go,
                         transform=-5,
                         function=lambda x: (np.sqrt(x[0]**2 + x[1]**2)) > 0,
                         synapse=0.01)
        # When the target != arm ee position, stop the ramp signal from
        # stopping (reaching to end position)
        nengo.Connection(target_diff_norm,
                         self.ramp_sig.end,
                         transform=-5,
                         function=lambda x: (np.sqrt(x[0]**2 + x[1]**2)) > 0,
                         synapse=0.01)

        # Disable the target_diff_norm when motor bypass
        nengo.Connection(self.motor_bypass.output,
                         target_diff_norm.neurons,
                         transform=[[-3.0]] * target_diff_norm.n_neurons)

        # ------ MOTOR PEN DOWN CONTROL ------
        pen_down = cfg.make_thresh_ens_net()

        # Pen is down by default
        nengo.Connection(bias_node, pen_down.input)

        # Cases when the pen should NOT be down
        nengo.Connection(self.ramp_sig.reset_hold,
                         pen_down.input,
                         transform=-1)
        nengo.Connection(self.ramp_sig.stop, pen_down.input, transform=-1)
        nengo.Connection(self.motor_stop_input.output,
                         pen_down.input,
                         transform=-1,
                         synapse=0.05)
        nengo.Connection(self.motor_bypass.output,
                         pen_down.input,
                         transform=-1)

        # Pen down signal feedback to rest of motor system (tells the ramp to
        # keep going, and the osc_net to use only kv1)
        nengo.Connection(pen_down.output, self.ramp_sig.go, transform=12)
        if arm_obj is not None:
            nengo.Connection(pen_down.output, osc_net.CB2_inhibit)

        # --------------- For external probes ---------------
        self.ramp_int_stop = self.ramp_sig.stop

        # Motor target output
        self.mtr_path_func_out = nengo.Node(size_in=2)
        nengo.Connection(func_eval_net.diff_func_outputs[0],
                         self.mtr_path_func_out[0],
                         transform=np.ones((1, mtr_func_dim)))
        nengo.Connection(func_eval_net.diff_func_outputs[1],
                         self.mtr_path_func_out[1],
                         transform=np.ones((1, mtr_func_dim)))

        # Arm segments joint locations
        if arm_obj is not None:
            self.arm_px_node = \
                nengo.Node(output=lambda t: arm_obj.position()[0])
            self.arm_py_node = \
                nengo.Node(output=lambda t: arm_obj.position()[1])
        else:
            self.arm_px_node = nengo.Node(0)
            self.arm_py_node = nengo.Node(0)

        # Arm ee zero_centered location
        self.zero_centered_arm_ee_loc = zero_centered_arm_ee_loc

        # Target ee zero_centered location
        self.zero_centered_tgt_ee_loc = func_eval_net.func_output

        # Pen down status
        self.pen_down = pen_down.output

        # Ramp signal outputs
        self.ramp = self.ramp_sig.ramp
        self.ramp_reset_hold = self.ramp_sig.reset_hold
        self.ramp_50_75 = self.ramp_sig.ramp_50_75

        # Decode index (number) bypass to monitor module
        self.dec_ind = nengo.Node(size_in=len(vocab.mtr.keys) + 1)