"make: execvp: /bin/sh: Argument list too long" error on standalone mode

Hi @canonrock16 . In principle you could probably work around the limitation of the number of file names, but this would only be a workaround. The underlying problem is that your code generates many Synapses objects, and each of these objects is translated into several C++ files (one for setting up the connections, one for updating the variables, one of propagating spikes, …). This will take a very long time to compile and is not necessary in your case. The general rule should be that if several Synapses objects connect between the same NeuronGroups and use the same equations, then they can be represented by a single Synapses object. If I am not mistaken, in your code all Synapses use the same equations (STDP, etc.) and connect within the single NeuronGroup. This means that you’d only need a single Synapses object. The code might be clearer and easier to use to if you use instead a small number, but it should not be 100s of them as in your current code.

To give you an idea of how you can transform the code, let me illustrate with some simpler version of your code. Currently you do something like this which will create 2×100 Synapses objects:

n = 1000  # number of neurons in one group
neuron_group_count = 100
R = 0.8
P = NeuronGroup(n * neuron_group_count, ...)
for i in range(neuron_group_count):
    group = P[int(i * n):int((i + 1) * n)]
    Pe = group[:int(n * R)]
    Pi = group[int(n * R):]

    Ce = Synapses(Pe, group, ...)
    Ce.connect(p=0.1)
    Ce.w = 6.0  # single weight for all Pe→group connections
    Ce.delay = round(random.uniform(0, 20), 2) * ms  # single delay

    Ci = Synapses(Pi, Pe, ...)
    Ci.connect(p=0.125)
    Ci.w = -5.0
    Ci.delay = 1 * ms

One option is to calculate all the indices and delays by hand and then connect everything up in the end:

n = 1000  # number of neurons in one group
neuron_group_count = 100
R = 0.8
P = NeuronGroup(n * neuron_group_count, ...)
source_indices = []
target_indices = []
delays = []
weights = []
for i in range(neuron_group_count):
    group = np.arange(int(i * n), int((i + 1) * n))
    Pe = group[:int(n * R)]
    Pi = group[int(n * R):]

    ci, cj = np.meshgrid(Pe, group, indexing='ij')  # all possible combinations of neurons in Pe and group
    select = np.random.rand(len(Pe), len(group)) < 0.1  # which pairs should be selected?
    n_select = np.sum(select)  # number of selected pairs
    
    # Store selected indices
    source_indices.extend(ci[select])
    target_indices.extend(cj[select])

    # Store corresponding weights/delays
    delays.extend(np.repeat(round(random.uniform(0, 20), 2), n_select)*ms)
    weights.extend(np.repeat(6.0, n_select))
 
    # Same thing for inhibitory connections
    ci, cj = np.meshgrid(Pi, Pe, indexing='ij')
    select = np.random.rand(len(Pi), len(Pe)) < 0.125
    n_select = np.sum(select)  # number of selected pairs
    source_indices.extend(ci[select])
    target_indices.extend(cj[select])
    delays.extend(np.repeat(1, n_select) * ms)
    weights.extend(np.repeat(-5.0, n_select))

# Now, create a *single* Synapses object storing everything
C = Synapses(P, P, '''...''', ...)
C.connect(i=source_indices, j=target_indices)
C.w = weights
C.delay = delays

You could of course clear this up a bit by putting some of the numpy calculation into a separate function, but I hope that the general idea is clear (if not, try it out with a small network and see what the variables contain at each step). Another option is slightly less efficient for the synapse creation, but more compact to write. It also makes the idea behind the connections much clearer, I think.

n = 1000  # number of neurons in one group
neuron_group_count = 100
R = 0.8
# Each neuron has a group label (integer number), and a flag whether it is excitatory or not
P = NeuronGroup(n * neuron_group_count, '''...
                                           group : integer (constant)
                                           is_excitatory : boolean (constant)
                    ''')
P.group = 'i // n'  # 0 for the first 1000 neurons, then 1 for the next 1000 neurons, etc.
P.is_excitatory = '(i % n) < int(R*n)'

C = Synapses(P, P, ...)
# excitatory connections
C.connect('is_excitatory_pre', p=0.1) 
C.delay = 'int(rand*2000)/100*ms'
C.weights = 6
# inhibitory connections
C.connect('not is_excitatory_pre and is_excitatory_post and group_pre == group_post', p=0.125)
C.w['not is_excitatory_pre'] = -5.0
C.delay['not is_excitatory_pre'] = 1*ms

There is a small difference between this and the previous code: here each excitatory connection has a different delay, whereas previously there was one delay value per group. This would be a bit more complicated to express in this framework. As I said before, you might also decide that it is more straightforward to have separate Ce and Ci synapses here instead of merging everything.

Hope that makes things a bit clearer! Best
Marcel