Closed heplesser closed 6 years ago
Thanks for writing this up. However, I disagree about the creation of NewCreate
, NewGetStatus
, etc.
In my opinion, no one will use them anyway until things break. Adding them just creates more work for us now and again when the transition occurs. Let's rather issue a good deprecation warning in the functions for 2.12.
Moreover, this is only relevant for SLI users, which are the smaller part of the community nowadays and we can provide support for the transition on the mailing list if required.
In PyNEST, most code will probably work seamlessly even with the change, e.g. consider
inhibitory = nest.Create("iaf_neuron", 10000)
nest.SetStatus(inhibitory, "V_m", -45.0)
@jougs I think your argument is sound.
GIDCollection
s were introduced as a compact representation of network nodes. They currently exist in two forms, either representing a contiguous range of GIDs by storing the first and last neuron, or by storing an explicit array of arbitrary GIDs. GIDCollection
s are currently only created by explicit conversion operations on the SLI level, and are accepted by the Connect
function as argument. GIDCollection
s support iteration, but not indexing or slicing.
"Current" here refers to the public master branch at 1fd378f8d95d64ed0af32fadd373a9500a68e719 .
GIDCollection
s are to represent the nodes of a network on the script level (i.e., outside the kernel). They shall be as compact as possible and support efficient operations, especially connection generation and status changes or queries.
The script shall control the lifetime of the GIDCollection
, i.e., a GIDCollection
should be deleted when the corresponding object is deleted at the script level, either explicitly or by going out of scope.
Consideration will be given first and foremost to the Python level, since it is the prime user interface.
GIDCollection
is contiguous if it represents a contiguous range of GIDsGIDCollection
is homogeneous if all GIDs in the collection refer to nodes of the same type (same model ID)GIDCollection
is primitive if it is contiguous and homogeneousGIDCollection
is composite if it is not primitiveThe following assumptions apply to non-explicit GIDCollection
s:
GIDCollection
objects are created rarely but looked up frequentlyGIDCollection
objects are immutableGIDCollection
objects will first and foremost be created by Create
calls; each such call will return a primitive collectionGIDCollection
holds information about the model ID of each GID in the collectionGIDCollection
may hold additional metadata (see section on Topology below for discussion on Metadata)GIDCollection
at most onceGIDCollection
GIDCollection
contains at least one primitive GIDCollection
with metadata, then all primitive GIDCollection
s in the GIDCollection
must hold the same metadata. Same-ness means in this case that the metadata pointers are identical.GIDCollection
s with metadata are never coalesced into a single primitive GIDCollection
, even if their ranges are adjacent and they have the same model type.It appears plausible to assume that GIDCollection
s will represent over 100, often over 1000 nodes, in extreme cases (4g benchmark), billions of GIDs.
When creating data-driven connections using one-to-one connect, one may require source and target lists that contain the same GID multiple times and in which order needs to be preserved, since GIDs are matched by position between source and target lists, and may also be matched to connection parameter lists. To keep the interface of Connect
clean, one may represent also such collections as GIDCollection
s. After a lengthy discussion, @terhorstd, @heplesser, @stinebuu and @hakonsbm concluded that such collections would behave so differently from ordinary GIDCollection
s that it would not be sensible to include them in the same class. They are therefore no further discussed here.
GIDCollection
sGIDCollection
s shall support the following operations:
GIDCollection
is equal to another (contains the same GIDs)GIDCollection
s/Enrns /iaf_psc_alpha 800 Create def % (1, 800)
/Inrns /iaf_psc_alpha 200 Create def % (801, 1000)
/nrns Enrns Inrns join def % addition % (1, 1000)
Enrns nrns << /rule /fixed_indegree /degree 100 >> Connect
10 Enrns MemberQ = % membership
/gc [ 10 20 30 ] cvgidcollection def % conversion from list
/Ilist Inrns cva def % conversion to array
Enrns Inrns eq = % equality
Enrns { ShowStatus } forall % iteration
Inrns 10 get = % indexing
Enrns 20 Take = % slicing
Enrns = nest.Create('iaf_psc_alpha', 800)
Inrns = nest.Create('iaf_psc_alpha', 200)
nrns = Enrns + Inrns
nest.Connect(Enrns, nrns, {'rule': 'fixed_indegree', 'degree': 100})
10 in Enrns % membership
gc = nest.GIDCollection([10, 20 ,30])
Ilist = list(gc)
for gid in Enrns:
print( nest.GetStatus( gid ) )
print( Inrns[10] )
print( Enrns[:20] )
This first use of metadata for GIDCollection
s is the subnet-free reimplementation of Topology (#481). Layers containing only a single neuron model can be represented by a primitive GIDCollection
, while layers with composite elements will require a composite GC with one primitive GC per component. All these primitive GCs are part of the same layer and thus share the same geometry. They therefore have all the same metadata. This motivates the requirement that all primitive GCs in a composite GC must have the same metadata.
GCs with metadata are never coalesced, even if they have adjacent ranges and identical model ids, since users may have specified composite elements with identical models.
For minor changes to the user interface, see #481.
GIDCollection
was constructedneurons = Eneurons + Ineurons
, Connect(E_neurons[:50], spike_det)
)GIDCollection
s cannot be converted to or from the Python level. This must become possible, including all operations listed above.GIDCollection
s are lightweight, unnecessary conversion between Python, SLI and C++ levels should be avoided. Therefore, the representation at the Python level should just be a pointer to the underlying C++ representation.GIDCollection
sNon-primitive GIDCollection
s are represented as lists of pointers to the GIDCollection
s they are constructed from. Any immediately adjacent GIDCollection
s of the same node type are combined into a primitive GIDCollection
.
GIDCollection
stores the model ID of the GIDs it representsGIDCollection
s is to reduce GID-based lookups for model type, existence of thread-siblings, etc in connection, setting and getting routinesTo provide necessary flexibility, a GIDCollectionMetadata
abstract base class will be provided. This class has only a minimal interface, all details are added by derived classes special to the use of the metadata, e.g., in topology:
class GIDCollectionMetadata
{
public:
GIDCollectionMetadata() {}
virtual ~GIDCollectionMetadata() = 0;
};
Since all elements of a composite GC must contain the same GC pointer, the composite GC can also return a metadata pointer.
For an example of metadata, see #481.
first version of GIDCollection UML:
@terhorstd I struggle to get Dia to run on OSX, so could you add the following additions to the UML diagram:
GIDCollectionMetadata
class, see aboveGIDCollectionMetadata const * get_metadata() const
method
GIDCollectionComposite
returns parts[0].get_metadata()
operator+()
raises an exception unless metadata_ == other.metadata_
(either neither have metadata, i.e., zero pointers, or both point to the same metadata object)I have created branch fix-455-gidcollections for work on this issue.
@terhorstd, @stinebuu, @hakonsbm and @heplesser discussed design via VC on 8 Nov. Here a summary of conclusions and open questions. This post is based on notes by @terhorstd .
Do not include "explicit collections" (general unsorted non-unique arrays) in GIDCollection interface
GIDCollectionComposite is always a flat container for GIDCollectionPrimitives.
Joining of primitives allowed only for same metadata (pointer equality)
If (different metadata OR different model_id): don't merge primitives but keep separate in composite
We will introduce fingerprints in order to properly handle ResetKernel()
. After using ResetKernel()
all metadata etc. will be gone, but we will still have the GIDs and/or other data the user might have extracted. It is important that we are not able to use these GIDs in functions such as Connect
, because the user might have created a new set of metadata that does not correspond to the old GIDCollection
, and errors will occur.
To solve this problem we introduce fingerprints. This will make it possible to check whether the GIDCollection
is valid. We will introduce a fingerprint in the Kernel, and in the GIDCollection
class. As a fingerprint, we will use a timestamp. Every time ResetKernel()
is called, the fingerprint in the Kernel will be updated. When a GIDCollection
is created, we can retrieve the fingerprint from the Kernel, and store it in the GIDCollection
class. It will then be possible to test against the Kernel fingerprint and see whether the GIDCollection
is valid when we use Connect
or other functions that rely on correctly created GIDCollection
s. If we have an invalid GIDCollection
, an IncorrectGIDCollection
will be raised.
To update on current progress on GIDCollections:
Everything works now, except for
Connect
, as described in #369. But this should be easy to implement.@hakonsbm: Can you please copy and update the information from this issue to a new document under extras/userdoc/md/
in our development branch. I'll close this issue once you did that. Many thanks!
@jougs I have created a new document in extras/userdoc/md
in our development branch with information from this issue, as you requested.
Many thanks. As the information is now in a safe place, I close this.
We decided in the Open NEST VC 8 Aug to removed subnets which represent structure in the simulation kernel and move all structure representation to the script layer in form of GIDCollections (see als #417). We further decided to
To ensure a smooth transition, it is essential that release 2.12 provides the full user interface of NEST 3.0, so that users can convert their scripts using the 2.12 release, before we release NEST 3.0. We should thus perform as much work as possible on master, before creating the 2.12 release branch (where we will add deprecation warnings) and the no-subnet-branch preparing 3.0.
In particular, we need to ensure that
GetConnections
supports GIDCollectionsFor
Create
and other related functions, we need to introduceNewCreate
and similar which return GIDCollections, so that they can coexist with the oldCreate
in 2.12. When converting scripts to 3.0 later, one will then just need to replaceNewCreate
withCreate
.