I know your question is java, but I really like this message bus style architecture for this type of thing.
Basically when messages are sent they get potentially two responses. The first is from the local cache, the second comes from the server once it gets connected.
I'm pretty sure you could adapt this architecture (rhino bus and nhib) to yours (MQ and hib) pretty easily.
Bi-directional associations in a class design are possible, but they always come at a hefty price, which you should know and must be willing to pay.
Generally, I like to avoid bi-directional associations with the only exception being performance. As you have mentioned, without knowing the other directions, you may have to loop through all the other objects to find the right one (or count them in your case). This may be costly, but it can also be worked around in other ways than creating a bi-directional relationship (f.ex. association classes with caches).
As you may well get hundreds of synapses, it certainly isn't good to loop over them to be able to check if something is connectable, so I think your bi-directional association may be a valid option here. It depends on what exactly you mean with this game
won't have too many connections.
If you can afford the looping, then I suggest you do so. If you do keep the bi-directional relationship, you will have to be extremely careful to keep your model consistent. Each time you touch one of these associations, you must ensure that you atomically update the whole model to become consistent again.
It's hard enough to ensure that each and every modification is correctly mirrored for all involved objects / associations, but once you add concurrency to that it gets even more ugly, because you do not ever want another thread to see the model in an intermediate state, where just one direction has been added/removed yet.
Even if you use tools like Hibernate, which support the bi-directional relationships out of the box, you get other trade-offs. For example, if you combine Hibernate with eager fetching you may well end up reading your whole neural network from the database, whenever you just call for one join. That's all part of the price to be payed.
Also note that omitting the bi-directional relationship and adding some helper class which keeps track of the number of inputs/outputs instead is not a good idea. For one, you split up the responsibility for consistent model updates to something outside of your main model, and second, the involved logic to keep things consistent needs to be added either way. You may accept the poor looping performance, or you may reasonably improve it by some cached lookup that is easier to update and need not necessarily be complete.
As a summary: Bi-directional relationships are possible, but should only be considered, when you cannot work around their absence in a feasible way.
Best Answer
It seems to me that priority is not a property of a number type if priority is determined based on the priorities of the other number types, so I think the best approach would be to place the number types in a List.
In other words, you have a List of Lists. The outer List determines the priority of the numbers contained within while the inner List contains the numbers themselves.
Suppose the position 0 in your outer list corresponds to priority A1, position 1 corresponds to priority A2, and position 2 corresponds to priority A3. If you add more priorities later, you can add more, but suffice to say that the number of priorities corresponds to the number of possible number types.
Suppose the user wishes to change the priority of those of A1 to A3. Well according to our List, we'd simply need to remove the first list of numbers and append it to the end. The second item in the list now is the first and the third is now the second. The priority of each number therefore is determined by its position in the list, so you know the priority of a number based on which list you retrieved it from.
I hope that's clear. If not, let me know and I'll try to clarify in my answer.