示例#1
0
 def simple_network(self):
     net = IzNetwork()
     net.add_neuron(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
     net.add_neuron(1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
     net.add_synapse(0, 1, 1, 5.0, False)
     net.add_synapse(1, 0, 1, 5.0, False)
     return (net, nemo.Simulation(net, nemo.Configuration()))
示例#2
0
def run_random(ncount, scount, duration=1000):
    """
    Construct a randomly connected network with n neurons each of which
    connects to m postsynaptic neurons.

    Inputs:
    ncount   -- Number of neurons
    scount   -- Number of synapses
    duration -- Duration of the simulation, in milliseconds
    """

    print "configure"
    conf = nemo.Configuration()

    print "construct"
    net = construct_random(ncount, scount)

    print "create simulation"
    sim = nemo.Simulation(net, conf)

    print "run simulation"
    for t in range(duration):
        # with firing and current stimulus
        fired = sim.step([2, 4, 5], [(6, 20.0), (7, -5.0)])
        print t, ":", fired
示例#3
0
 def test_set_neuron(self):
     """
     The set_neuron method supports either vector or scalar input. This
     test calls set_synapse in a large number of ways, checking for
     catastrophics failures in the boost::python layer
     """
     net = IzNetwork()
     ncount = 1000
     net.add_neuron(range(ncount), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
     for test in range(1000):
         self.check_neuron_function(net.set_neuron, ncount=1000)
     sim = nemo.Simulation(net, nemo.Configuration())
     for test in range(1000):
         self.check_neuron_function(sim.set_neuron, ncount=1000)
示例#4
0
 def __init__(self, timestep, min_delay, max_delay):
     """Initialize the simulator."""
     self.net = nemo.Network()
     self.conf = nemo.Configuration()	
     self.initialized = True
     self.num_processes = 1
     self.mpi_rank = 0
     self.min_delay = min_delay
     self.max_delay = max_delay
     self.gid = 0
     self.dt = timestep
     self.simulation = None
     self.stdp = None
     self.time = 0
     self._fired = []
示例#5
0
    def test_sim_set_neuron_vector(self):
        """
        Test for failures in vector/scalar form of set_neuron

        The set_neuron_parameter methods supports either vector or scalar
        input. This test calls this function in a large number of ways,
        checking for catastrophics failures in the boost::python layer
        """
        net = IzNetwork()
        conf = nemo.Configuration()
        pop = range(1000)
        for n in pop:
            net.add_neuron(n, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
        sim = nemo.Simulation(net, conf)
        self.check_set_neuron_vector(sim, pop)
示例#6
0
    def compress(self):
        global _created_connection
        DelayConnection.compress(self)

        # check that limitations are met
        if _created_connection:
            raise NotImplementedError(
                "Current version only supports a single connection.")
        _created_connection = True
        if self.source is not self.target:
            raise NotImplementedError(
                "Current version only supports a single group.")
        if not isinstance(self.W[0, :], SparseConnectionVector):
            raise NotImplementedError(
                "Current version only supports sparse matrix types.")

        # now upload to nemo
        self.nemo_net = nemo.Network()
        if pycuda is not None:
            self.nemo_use_gpu = True
        else:
            self.nemo_use_gpu = False
        # create dummy neurons
        self.nemo_input_neuron_idx = self.nemo_net.add_neuron_type('Input')
        self.nemo_net.add_neuron(self.nemo_input_neuron_idx,
                                 range(len(self.source)))
        # create synapses
        for i in xrange(len(self.source)):
            Wrow = self.W[i, :]
            Wdelay = self.delay[i, :]
            ind = asarray(Wrow.ind)
            delay = asarray(Wdelay / ms, dtype=int) + 1
            weight = asarray(Wrow, dtype=float32)
            if len(ind):
                #self.nemo_net.add_synapse(i, ind, delay, weight, False)
                self.nemo_net.add_synapse(i, ind.tolist(), delay.tolist(),
                                          weight.tolist(), False)
        # configure
        self.nemo_conf = nemo.Configuration()
        if self.nemo_use_gpu:
            self.nemo_conf.set_cuda_backend(0)
        else:
            self.nemo_conf.set_cpu_backend()
        # simulation object
        self.nemo_sim = nemo.Simulation(self.nemo_net, self.nemo_conf)
示例#7
0
def run_random(ncount, scount, duration=1000):
    print "configure"
    conf = nemo.Configuration()
    print "construct"
    net = construct_random(ncount, scount)
    print "create simulation"
    sim = nemo.Simulation(net, conf)
    print "run simulation"
    for t in range(duration):
        # with firing and current stimulus
        # fired = sim.step([2, 4, 5], [(6, 20.0), (7, -5.0)])
        fired = sim.step()
        print t, ":", fired

    # Read back a few synapse values.
    ids = sim.get_synapses_from(0)
    print sim.get_targets(ids)
    print sim.get_delays(ids)
    print sim.get_weights(ids)
    print sim.get_plastic(ids)
示例#8
0
    def prepare(self):
        global _created_network
        if _created_network:
            raise NotImplementedError(
                "Current version only supports a single network object.")
        _created_network = True

        Network.prepare(self)
        if hasattr(self, 'clocks') and len(self.clocks) > 1:
            raise NotImplementedError(
                "Current version only supports a single clock.")

        if pycuda is not None:
            self.nemo_use_gpu = True
#            self.nemo_use_gpu = False
#            log_warn('brian.experimental.cuda.briantonemo',
#                     'GPU available but not yet supported, using CPU.')
        else:
            self.nemo_use_gpu = False

        # add a NetworkOperation that will be used to carry out the propagation
        # by NeMo. The individual Connection objects push their spikes into a
        # global queue (this is done by NemoNetworkConnectionPropagate) and then
        # the NemoNetworkPropagate NetworkOperation object propagates the
        # accumulated effect of the spikes to the target NeuronGroup objects.
        nemo_propagate = NemoNetworkPropagate(self, self.clock)
        self.nemo_propagate = nemo_propagate
        # we add this object to the network and don't need to prepare() again
        # because we rebuild the update schedule below.
        self.add(nemo_propagate)

        # create virtual neurons for Nemo, the virtual neurons are either source
        # neurons or target neurons. For each Connection, we create a group of
        # source neurons (or re-use if it has already been created), and a
        # group of target neurons. Each target group and target variable has
        # a corresponding virtual group. In all cases, we work with the _owner
        # of the NeuronGroup so that we don't create multiple groups for each
        # subgroup.
        print 'Nemo network virtual neuron groups:'
        self.group_offset = group_offset = {}
        total_neurons = 0
        self.nemo_managed_connections = []
        self.nemo_propagate_targets = []
        network_ops_to_remove = []
        all_connections = []
        for C in self.connections:
            if isinstance(C, MultiConnection):
                all_connections.extend(C.connections)
            else:
                all_connections.append(C)
        for C in all_connections:
            # We handle only Connection and DelayConnection objects. For the CPU
            # version at least, we can rely on Brian to fall back to its
            # default behaviour otherwise.
            if C.__class__ is not DelayConnection and C.__class__ is not Connection:
                continue
            # Nemo cannot handle modulation, so we check for this case
            if C._nstate_mod is not None:
                log_warn(
                    "brian.experimental.cuda.briantonemo",
                    "Synaptic modulation is not supported in Nemo, skipped this Connection."
                )
                continue
            # Add the source neuron group
            G = C.source._owner
            if id(G) not in group_offset:
                group_offset[id(G)] = total_neurons
                print '- Source group, length', len(G), 'indices %d:%d' % (
                    total_neurons, total_neurons + len(G))
                total_neurons += len(G)
            # Add the (target neuron group, target variable) virtual group
            key = (id(C.target._owner), C.nstate)
            if key not in group_offset:
                group_offset[key] = total_neurons
                varname = get_connection_variable(C)
                print '- Target group, length', len(
                    G), 'variable', varname, 'indices %d:%d' % (
                        total_neurons, total_neurons + len(G))
                target_offset = total_neurons
                targetslice = slice(target_offset,
                                    target_offset + len(C.target))
                targetvar = C.target._S[C.nstate]
                self.nemo_propagate_targets.append(
                    (varname, targetvar, targetslice))
                total_neurons += len(C.target)
            self.nemo_managed_connections.append(C)
            if C.__class__ is DelayConnection:
                network_ops_to_remove.append(C.delayed_propagate)
        self.total_neurons = total_neurons

        # now upload to nemo
        self.nemo_net = nemo.Network()

        # create dummy synapse type
        self.synapse_type = self.nemo_net.add_synapse_type()
        self.nemo_propagate.synapse_type = self.synapse_type

        # create dummy neurons
        self.nemo_input_neuron_idx = self.nemo_net.add_neuron_type(
            'Input', [self.synapse_type])
        self.nemo_net.add_neuron(self.nemo_input_neuron_idx,
                                 range(total_neurons))

        # add connections and upload synapses to nemo
        total_synapses = 0
        print 'Nemo network synapses:'
        for C in self.nemo_managed_connections:
            # We handle subgrouping using the source and target offset
            source_offset = group_offset[id(
                C.source._owner)] + C.source._origin
            target_offset = group_offset[(id(
                C.target._owner), C.nstate)] + C.target._origin
            dt = C.source.clock.dt
            # We replace the propagate method of the Connection with a nemo
            # version, which adds the spikes to a dynamic stack in the
            # NemoNetworkPropagate object, which is called after the connections
            # have been processed by Brian. Note that this way of doing things
            # only works for the CPU, for the GPU we will need to replace
            # do_propagate instead.
            C.propagate = NemoNetworkConnectionPropagate(self, source_offset)
            # create synapses
            this_connection_synapses = 0
            for i in xrange(len(C.source)):
                # Need to handle Connection/DelayConnection, and sparse/dense
                # matrix types
                Wrow = C.W[i, :]
                if C.__class__ is DelayConnection:
                    Wdelay = C.delay[i, :]
                else:
                    Wdelay = zeros(len(Wrow))
                if isinstance(Wrow, SparseConnectionVector):
                    ind = (Wrow.ind + target_offset)
                else:
                    ind = range(target_offset, target_offset + len(Wrow))
                delay = (1 + asarray(Wdelay / dt, dtype=int))
                # Need to update this when NeMo gets support for longer delays
                if self.nemo_use_gpu and amax(delay) > 512:
                    raise NotImplementedError(
                        "Current version of NeMo with GPU backend has a maximum delay of 512 steps."
                    )
                if not self.nemo_use_gpu and amax(delay) > 64:
                    raise NotImplementedError(
                        "Current version of NeMo with CPU backend has a maximum delay of 64 steps."
                    )
                weight = asarray(Wrow, dtype=float32)
                total_synapses += len(weight)
                this_connection_synapses += len(weight)
                if len(ind):
                    self.nemo_net.add_synapse(self.synapse_type,
                                              i + source_offset, ind, delay,
                                              weight, False)
            print '-', C.__class__.__name__,
            print 'from source group of', len(C.source), 'neurons',
            print 'to target group of', len(C.target), 'neurons,',
            print 'variable %s,' % get_connection_variable(C),
            print 'matrix type %s,' % C.W.__class__.__name__,
            print 'number of synapses', this_connection_synapses

        # debug print the propagation targets
        print 'Nemo network propagation targets:'
        for varname, targetvar, targetslice in self.nemo_propagate_targets:
            print '- Variable', varname, 'indices %d:%d' % (targetslice.start,
                                                            targetslice.stop)

        # remove the delayed_propagate functions which are used by
        # DelayConnection and will already have been inserted into the network
        # at this point (as they are in the contained_objects of
        # DelayConnection).
        for k, v in self._operations_dict.iteritems():
            v = [f for f in v if not f in network_ops_to_remove]
            self._operations_dict[k] = v

        # We changed lots of propagate functions so we need to rebuild the
        # update schedule to make use of them
        self._build_update_schedule()

        print 'Nemo network total neurons:', total_neurons
        print 'Nemo network total synapses:', total_synapses

        # configure
        self.nemo_conf = nemo.Configuration()
        if self.nemo_use_gpu:
            self.nemo_conf.set_cuda_backend(0)
        else:
            self.nemo_conf.set_cpu_backend()
        # simulation object
        self.nemo_sim = nemo.Simulation(self.nemo_net, self.nemo_conf)
示例#9
0
net = nemo.Network()

# Excitatory neurons
for nidx in range(800):
    r = random.random()**2
    c = -65.0+15*r
    d = 8.0 - 6.0*r
    net.add_neuron(nidx, 0.02, 0.2, c, d, 5.0, 0.2*c, c)
    targets = range(1000)
    weights = [0.5*random.random() for tgt in targets]
    net.add_synapse(nidx, targets, 1, weights, False)

# Inhibitory neurons
for nidx in range(800,1000):
    nidx = 800 + n
    r = random.random()
    a = 0.02+0.08*r
    b = 0.25-0.05*r
    c = -65.0
    net.add_neuron(nidx, a, b, c, 2.0, 2.0, b*c, c)
    targets = range(1000)
    weights = [-random.random() for tgt in targets]
    net.add_synapse(nidx, targets, 1, weights, False)

conf = nemo.Configuration()
sim = nemo.Simulation(net, conf)
for t in range(1000):
    fired = sim.step()
    print t, ":", fired
示例#10
0
    def test_get_synapse(self):
        """
        Test scalar and vector form of synapse getters

        Synapse getters have both scalar and vector forms. To test these,
        construct a network with fixed connectivity where all synapse
        properties are functions of the source and target, then read back and
        verify that the values are as expected.
        """
        def delay(source, target):
            return 1 + ((source + target) % 20)

        def plastic(source, target):
            return (source + target) % 1 == 0

        def weight(source, target):
            return float(source) + float(target)

        ncount = 100

        net = IzNetwork()
        for src in range(ncount):
            net.add_neuron(src, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
            for tgt in range(src + 1):
                net.add_synapse(src, tgt, delay(src, tgt), weight(src, tgt),
                                plastic(src, tgt))

        conf = nemo.Configuration()
        sim = nemo.Simulation(net, conf)

        def check_scalar(x, known_source, sid, source, target):
            self.assertEqual(known_source, source)
            self.assertEqual(x.get_synapse_delay(sid), delay(source, target))
            self.assertEqual(x.get_synapse_weight(sid), weight(source, target))
            self.assertEqual(x.get_synapse_plastic(sid),
                             plastic(source, target))

        def check(x):
            for src in range(ncount):
                all_synapses = x.get_synapses_from(src)
                # read a random number of these out-of-order
                n_queried = random.randint(1, len(all_synapses))
                queried = random.sample(all_synapses, n_queried)
                if len(queried) == 1:
                    queried = queried[0]
                sources = x.get_synapse_source(queried)
                targets = x.get_synapse_target(queried)
                if n_queried == 1:
                    check_scalar(x, src, queried, sources, targets)
                else:
                    for (sid, qsrc, tgt) in zip(queried, sources, targets):
                        check_scalar(x, src, sid, qsrc, tgt)

        def check_iterator(x):
            # Make synapse getter can deal with the iterator returned by the
            # the synapse query
            for src in range(ncount):
                srcs = x.get_synapse_source(x.get_synapses_from(src))

        check(net)
        check(sim)
        check_iterator(net)
        check_iterator(sim)
示例#11
0
 def test_get_synapses_from_unconnected(self):
     net = IzNetwork()
     net.add_neuron(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
     self.assertEqual(len(net.get_synapses_from(0)), 0)
     sim = nemo.Simulation(net, nemo.Configuration())
     self.assertEqual(len(sim.get_synapses_from(0)), 0)