USAGE:


   #import structure

SYNOPSIS:

Provides template classes

     RingBuffer
     Directory
     List
     Graph

to provide basic data structures for arbitrary objects.

TEMPLATE CLASS RingBuffer:

Constructor:

class <T> RingBuffer x(int size):
creates ring buffer for objects of class T

Variables:

readonly int numel
nr of elements in ring

Methods:

insert (T a):
insert a new element at pos 0 and shift remaining els back (oldest el falls out)
T get(int i=0):
get reference to i-th element (i%size)
T push(T x):
equivalent to insert
T pop(T x):
get & remove element
void rotate(int steps):
rotate ringbuffer by given nr of steps
void clear(void):
clear ringbuffer to 0 entries

TEMPLATE CLASS Directory:

Provides a class to store and retrieve objects via a char* key.

Constructors:


   class Directory x(void);

Variables:

readonly numel
nr of elements

Methods:

char *firstkey():
char *lastkey():
lowest and highest char key (NULL, if directory empty)
T get(char *key):
return (reference to) first element with given key in table
void set(char *key, T x):
replace object with key key by x
void insert(char *key, T x):
insert new object with key key. If key already exists: ???
int remove(char *key1, int num=1):
int remove(char *key1, char *key2):
remove object(s) with keys between key1 and key2 (inclusive). If the default values of key2 and maxnum are kept, this will be taken as requesting removal of the first el with key=key1.
void merge(class Directory other, char *key1=NULL, char *key2=NULL):
merge range key1..key2 of Directory other into current Directory. The merged elements will become removed from other.
Directory <T> union(Directory other, char *first, char *last=NULL):
create new list consisting of union of (references to) elements both in list other and current list.
for_elements(void(*fun)(char *key, T x), char *first=NULL, char *last=NULL):
iterate function fun over (part of the) table
Directory <T> subset(float (*pred)(T x), char *first=NULL, char *last=NULL):
create new list consisting of (references to) elements in range start..end (exclusive) for which pred() is true.
clear():
remove all elements from the table

TEMPLATE CLASS List:

Implements a list data type for an arbitrary class T. (Note: current implementation actually follows "array strategy", i.e., lookup is cheap, insert (moving tail!) expensive).

Usage:


     class <T> List x();

will create an instance x that can hold a sorted list of instances of class T. An optional int argument can request a minimal initial capacity.

Variables:

readonly int end:
nr of elements currently in list.
readonly int is_sorted:
1 (-1) if list has a comparison function (cf. below) and is sorted in ascending (descending) order. Value 0 indicates that list may have become (but is not guaranteed to be!) unsorted or has no comparison function.
readonly int capacity:
nr of currently allocated memory positions for elements.

Methods:

T get(int i):
return reference to list element at position i, throws badop:index exception, when i is not in legal range i..end-1.
set(int i,T x):
replace list element at position i by x. Throws badop:index exception, when i is not in legal range i..end-1
sort(cmp):
enforce sorting of list, using comparison function

              float cmp(class T a, class T b)

that compares two T arguments and returns a value < 0 if a<b, >0 if a>b and 0 if a==b. This comparison function will then also be used by any other subsequent list operations that make use of an order relation.
sort():
analogous, but re-use most recently specified cmp function and act only if an intermediate operation (such as set() or insert(pos,x) has destroyed a previously established sorting order. NOTE: sort() assumes that cmp's behavior has not been changed (e.g., through global variables) since the most recent sort.
sort(0):
disable sorting function. Subsequent operations behave as if no sorting function were defined.
void revert():
invert list order
void insert(T x):
if a comparison function has been defined and the list is sorted: insert new element x such that sorting order stays intact. Otherwise simply append x after last list element.
void insert(int pos, T x)
insert x at position pos (0=start), shifting all elements at former positions pos..end-1 one position up (this may destroy sorting order). Throws a badop:index exception, if pos is not in the legal range 0..end.
void insert(int pos,class List src, int start=0,int end=9999999):
insert elements from range start..end of list src into current list. Existing elements will be shifted up so that the first inserted element will occupy position pos. Src must not be identical with the current list.
void merge(class List other, int start=0, int end=99999999):
merge range start..end of list other into current list. The merged elements will become removed from other.
subtract(List other, int start=0,int end=999999):
remove from current list all those elements that occur in the range start..end of list other. List other must be different from the current list.
int remove(int first, int num=1):
starting at position first, remove up to num elements from list. Return nr of removed elements.
remove_if(float (*pred)(T x), int start=0,int end=9999999):
remove all elements from the range start..end (with end not included) for which the predicate pred(x) is nonzero,
for_elements(void (*fun)(T), int first=0, int end=9999999, int stride=1):
call function fun(x) for all list elements in range first..end, using stride as the step increment from position first (if first>end, a non-empty range requires stride<0).
for_elements(void (*fun)(int i, T x), int first=0, int end=9999999, int stride=1):
analogous, but for function fun() that passes for each element x also its list position i.
int closest(T x, float dist(T,T), int first=0, int end=999999, int stride):
find position of list element y in range first..end (with end excluded) for which function dist(x,y) has smallest absolute value, using step increment stride to traverse the range (starting at from). In case of multiple minima of same magnitude, the first one found is returned.
List <T> neighbors(T x, int num, float dist(T,T), int first=0, int end=999999, int stride):
create new list containing (references to) first num closest elements (according to smallest dist() value) in range first..end (with end excluded), using step increment stride to traverse the range (starting at from). The returned list will contain the elements ordered by increasing distance.
List <T> subset(int *pos):
create new list of (references to) elements with positions specified in array pos.
List <T> subset(float (*pred)(T x), int start=0,int end=999999):
create new list consisting of (references to) elements in range start..end (exclusive) for which pred() is true.
List <T> intersection(List other, int start=0,int end=999999):
create new list consisting of (references to) elements both in list other and current list.
List <T> union(List other, int start=0,int end=999999):
create new list consisting of union of (references to) elements both in list other and current list.
List <T> difference(List other, int start=0,int end=999999):
create new list consisting of those elements of the current list that are not in the range start..end of list other.
void reserve(int size):
if capacity<size, raise it to size.
void clear():
remove all elements from current list (elements whose ref count drops to zero will become destroyed).

TEMPLATE CLASS Graph:

a general graph data type which allows to create nodes, connect them with different types of edges, and associate float vectors, text labels and/or user specified object types with nodes and/or edges.

CONSTRUCTORS:

graph(int dimn, int dime1, ...,dimek):
create graph whose nodes carry an optional string label and a dimn dimensional node data vector. Created nodes can be connected with edges from k different edge types (identified by an integer index 0,1,..k-1). Edge type i-1 carries an dimei dimensional float vector plus an (optional) string label with each edge. If dimei=0, the edge has the string label (which may remain NULL) as its only data.
When one float vector and one text label for each node and each edge are insufficient, the following constructor calls permit graphs with nodes that can (additionally to a float vector) also attach instances of a user-specified object type to each node and can be connected by up to three additional edge types which can carry object instances (instead of float vectors):
<T0> graph(int dimn, int dime1, ...,dimek):
As before, but now each node additionally can carry a node object of type T0.
<T0,T1> graph(int dimn, int dime1, ..,dimek):
As before, but now there is one additional edge type (in addition to the vector-carrying edge types 0..k-1) that (instead of a float vector) carries an object of type T1. Access functions to this additional edge type are identified by the keyword edge1 (instead of just edge).
<T0,T1,T2> graph(int dimn, int dime1, ...,dimek):
As before, but now there are two additional edge types (identified by keywords edge1 and edge2 resp.), carrying object types T1 and T2, resp.
<T0,T1,T2,T3> graph(int dimn, int dime1, ...,dimek):
Analogous, but with three additional object-carrying edge types.
It is legal that already dime1 is absent, in which case the graph will only have edge types of the object-carrying kind.

Methods involving nodes only:

int insert_node(float *data)
insert a node and initialize its vector data
int insert_node(T0 obj)
insert a node and initialize its node object - void remove_node(int id) remove node with id id.
void set_node_partition(int id, int partition)
mark node id as belonging to a subset identified by the value of partition. Subsets are disjoint, except for partition=0, which always comprises all nodes.
int get_node_partition(int id)
retrieve to which partition a given node is currently assigned.
for_nodes(float *pcFmt, void (*f)(float*), int partition=0):
iterate function f() over all nodes (if partition!=0, iteration is restricted to the nodes that belong to the indicated partition). At each step, the caller passes to f() node data according to format string pcFmt.
for_nodes(void (*f)(T0), int partition=0):
similar, but with function f() which receives node object on each call
int closest(float *data, float (*Dist)(float*,float*),float *mindist=NULL,int partition):
int closest(T0 obj, float (*Dist)(T0,T0),float *mindist=NULL,int partition):
return index of node of current graph whose node data vector (or node object, resp.) is closest to a given vector data (or object, resp). The min distance is returned when mindist!=NULL. partition permits to restrict the set of admissible nodes on the current graph.
int closest(class Graph graph2,float (*Dist)(T0,T0),int *i2=NULL,float mindist=NULL,int partition):
int closest(class Graph graph2, int partition2, float (*Dist)(T0,T0),int *i2=NULL,float mindist=NULL,int partition):
return index of node of current graph that is closest to a node i2 of graph graph2. i2 and the min distance are returned, when non-NULL parameters have been specified. partition and partition2 permit to restrict the set of admissible nodes on the current graph and on graph2.
int neighbors(T x, int *nb, float dist(T,T), int partition=0):
find ids of first dimof(nb) closest nodes (according to smallest dist() value) in partition partition of the current graph. Fill nb with the ids ordered by increasing distance. Return nr of ids filled into nb.
for_neighbors_of(int id, void fun(T), int radius=1):
for_neighbors_of(int id, void fun(T,int), int radius=1):
iterate function fun() over node objects of node id and its neighbors within a maximal graph distance of radius edges (inclusively). The 2nd version also passes with each function call the id of the currently visited node.
set_node(int id, float *data, char *mask=NULL):
get_node(int id, float *data, char *mask=NULL):
void set_node_label(int id, char *label):
char *get_node_label(int id):
set/get node vector data/label
void set_node_obj(int id, T0 obj):
T0 get_node_obj(int id):
void merge(class Graph other, int partition=0):
merge nodes in partition partition of graph other into current graph. The merge will include all edges connecting nodes from the merged partition. The merged elements will become removed from other. In addition, all edges between the partition and the rest of other will become deleted.
clear()
remove all nodes and edges
compactify_ids(int *list=NULL)
compactify node ids to the contiguous range 0..nodes-1. This is useful after node deletions, which may have left unused holes in the index range. Note that after this the indices of nodes will have changed! To keep track of such changes, one may specify an array list filled with previous node index values, which will then become updated with their new values (entries that did not specify used node index values will become replaced by -1).

Methods involving edges:

Edges can be directed or symmetric (=undirected) (directionality is treated separate from edge types, cf. below). A pair of nodes can be connected (in each direction) by maximally one directed edge, or instead by a single symmetric edge. All edge iterator functions have an additional mode parameter which allows to restrict iterations with regard to edge directionality:

    mode = OUT_E : visit all outward directed edges of a node
    mode = INP_E : visit all inward directed edges of a node
    mode = SYM_E : visit all symmetric edges of a node
    mode = SYM1_E : visit all symmetric edges of a node, but
                     with the additional restriction that
                     node-id1 < node-id2 to ensure that each symmetric
                     edge is visited only once when iterating over
                     all nodes.

    mode = 0: (the default) equivalent to
              OUT_E+INP_E+SYM_E or OUT_E+INP_E+SYM1_E when
              iterating over selected or all nodes, resp.

void use_edge_type(int type):
void insert_edge(int from, int to, float *data=NULL):
void insert_symedge(int n1, int n2, float *data=NULL):
insert float vector edge or symmetric edge of current type.
void insert_edge1(int from, int to, T1 obj):
void insert_symedge1(int n1, int n2, T1 obj):
insert object edge or symmetric edge of additional type 1. (analogous calls for additional types 2 and 3).
void remove_edge(int from, int to):
void remove_edge(int *piFrom, int *piTo):
remove edge(s) between two nodes/two node sets
void remove_edge1..3(int from, int to):
remove edge(s) for additional type between two nodes/two node sets
void set_edge_vector(int from, int to, float *data):
float *get_edge_vector(int from, int to):
void set_edge1_obj1(int from, int to, T1 obj):
T1 get_edge1_obj(int from, int to):
int for_edges(void(*fun)(int,int), int mode=0):
int for_edges_of(int node, void (*fun)(int,int), int mode=0):
int for_edges(char *fmt, void(*fun)(float*), int mode=0):
int for_edges_of(int node, char *fmt, void(*fun)(float*), int mode=0):
iterate function fun() over all vector edges of type layer, passing node index pair or edge data according to fmt
int for_edges1(void(*fun)(int,int)), int mode=0):
iterate function fun() over all object edges of additional type 1, passing edge object with each call. Analogous calls for additional types 2 and 3.
int for_edges1(void(*fun)(T1)), int mode=0):
int for_edges1_of(int node, void(*fun)(int,int), int mode=0):
int for_edges1_of(int node, void(*fun)(T1), int mode=0):
Analogous calls, but for edges connected to a single node. mode=1 only outgoing, mode=-1 only ingoing, mode=0 both types of edges.
int *shortest_path(int from, int to, float *dist=NULL, int distidx=0, int reuse=0):
find shortest path from node from to node to, using as distance value the edge data element at position distidx. The routine will return a newly allocated array with one element for each node in the path (including start from and end to). If dist!=NULL, deposit also the distance along the shortest path. When reuse=1, a new call will check if from and distidx is unchanged. If so, a recomputation will be based on the (internally stored) result of the most previous call, assuming that the graph topology has not been changed. This allows to retrieve a number of paths to different destination points without excessive recomputations.
float *mindist(int from, int *piPrev, int distidx=0):
compute and return array with one slot per element in the current node index range. Those slots i that correspond to existing nodes contain the min path distance from node from to that node i. An infinite distance is indicated by Infty. Slots that correspond to unused gaps in the index range contain the value NaN. If piPrev is non-null, it is filled for each node slot with the predecessor of the shortest path connecting that node to the starting node from (i.e., piPrev will be of the same dimension as the returned distance array).

FILE

structure.c