8. adjacency
— A class for storing and handling adjacency tables.¶
This module defines a specialized array class for representing adjacency of items of a single type. This is e.g. used in mesh models, to store the adjacent elements.

class
adjacency.
Adjacency
(data=[], dtyp=None, copy=False, normalize=True)[source]¶ A class for storing and handling adjacency tables.
An adjacency table defines a neighbouring relation between elements of a single collection. The nature of the relation is not important, but should be a binary relation: two elements are either related or they are not.
Typical applications in pyFormex are the adjacency tables for storing elements connected by a node, or by an edge, or by a node but not by an edge, etcetera.
Conceptually the adjacency table corresponds with a graph. In graph theory however the data are usually stored as a set of tuples (a,b) indicating a connection between the elements a and b. In pyFormex elements are numbered consecutively from 0 to nelems1, where nelems is the number of elements. If the user wants another numbering, he can always keep an array with the actual numbers himself. Connections between elements are stored in an efficient twodimensional array, holding a row for each element. This row contains the numbers of the connected elements. Because the number of connections can be different for each element, the rows are padded with an invalid elements number (1).
A normalized Adjacency is one where all rows do not contain duplicate nonnegative entries and are sorted in ascending order and where no column contains only 1 values. Also, since the adjacency is defined within a single collection, no row should contain a value higher than the maximum row index.
Parameters:  data (int array_like) – Data to initialize the Connectivity. The data should be 2dim with
shape
(nelems,ncon)
, wherenelems
is the number of elements andncon
is the maximum number of connections per element.  dtyp (float datatype, optional) – Can be provided to force a specific int data type. If not, the
datatype of
data
is used.  copy (bool, optional) – If True, the data are copied. The default setting will try to use
the original data if possible, e.g. if
data
is a correctly shaped and typednumpy.ndarray
.  normalize (bool, optional) – If True (default) the Adjacency will be normalized at creation time.
 allow_self (bool, optional) – If True, connections of elements with itself are allowed. The default (False) will remove selfconnections when the table is normalized.
Warning
The
allow_self
parameter is currently inactive.Examples
>>> A = Adjacency([[1,2,1], ... [3,2,0], ... [1,1,3], ... [1,2,1], ... [1,1,1]]) >>> print(A) [[1 1 2] [ 0 2 3] [1 1 3] [1 1 2] [1 1 1]] >>> A.nelems() 5 >>> A.maxcon() 3 >>> Adjacency([[]]) Adjacency([], shape=(1, 0))

maxcon
()[source]¶ Return the maximum number of connections for any element.
This returns the row width of the Adjacency.

sortRows
()[source]¶ Sort an adjacency table.
This sorts the entries in each row of the adjacency table in ascending order and removes all columns containing only 1 values.
Returns: Adjacency – An Adjacency with the same nonnegative data but each row sorted in ascending order, and no column with only negative values. The number of rows is the same as the input, the number of columns may be lower. See also
normalize()
 also removes self and duplicate entries
Examples
>>> a = Adjacency([[ 0, 2, 1, 1], ... [1, 3, 1, 1], ... [ 3, 1, 0, 1], ... [1, 1, 1, 1]]) >>> a.sortRows() Adjacency([[1, 1, 2], [1, 1, 3], [ 0, 1, 3], [1, 1, 1]]) >>> a = Adjacency([[ 0, 2, 1, 1], ... [1, 3, 1, 1], ... [ 3, 1, 0, 1], ... [1, 1, 1, 1]],normalize=False) >>> a.sortRows() Adjacency([[ 0, 1, 2], [1, 1, 3], [ 0, 1, 3], [1, 1, 1]])

normalize
()[source]¶ Normalize an adjacency table.
A normalized adjacency table is one where each row:
 does not contain the row index itself,
 does not contain duplicates,
 is sorted in ascending order,
and that has no columns with all 1 values.
By default, an Adjacency gets normalized when it is constructed. Performing operations on an Adjacency may however leave it in a nonnormalized state. Calling this method will normalize it again. Obviously this can also be obtained by creating a new Adjacency with self as data.
Returns: Adjacency – An Adjacency object with shape (self.shape[0],maxc), with maxc <= adj.shape[1]
. A rowi
of the Adjacency contains the unique nonnegative numbers except the valuei
of the same rowi
in the original, and is possibly padded with 1 values.Examples
>>> a = Adjacency([[ 0, 0, 0, 1, 2, 5], ... [1, 0, 1, 1, 1, 3], ... [1, 1, 0, 1, 1, 2], ... [1, 1, 1, 1, 1, 3], ... [1, 1, 1, 1, 1, 1], ... [1, 1, 0, 1, 1, 5]],normalize=False) >>> a.normalize() Adjacency([[ 1, 2, 5], [1, 0, 3], [1, 1, 0], [1, 1, 1], [1, 1, 1], [1, 1, 0]]) >>> Adjacency(a) Adjacency([[ 1, 2, 5], [1, 0, 3], [1, 1, 0], [1, 1, 1], [1, 1, 1], [1, 1, 0]])

pairs
()[source]¶ Return all pairs of adjacent element.
Returns: int array – An int array with two columns, where each row contains a pair of adjacent elements. The element number in the first column is always the smaller of the two element numbers. Examples
>>> Adjacency([[1,1],[0,2],[1,0]]).pairs() array([[0, 1], [1, 2]])

symdiff
(adj)[source]¶ Return the symmetric difference of two adjacency tables.
Parameters: adj (Adjacency) – An Adjacency with the same number of rows as self
.Returns: Adjacency – An adjacency table of the same length, where each row contains all the (nonnegative) numbers of the corresponding rows of self
andadj
, except those that occur in both.Examples
>>> A = Adjacency([[ 1, 2,1], ... [ 3, 2, 0], ... [ 1,1, 3], ... [ 1, 2,1], ... [1,1,1]]) >>> B = Adjacency([[ 1, 2, 3], ... [ 3, 4, 1], ... [ 0,1, 2], ... [ 0, 3, 4], ... [1, 0,1]]) >>> A.symdiff(B) Adjacency([[1, 1, 1, 3], [1, 0, 2, 4], [1, 0, 1, 3], [ 0, 1, 2, 4], [1, 1, 1, 0]])

frontGenerator
(startat=0, frontinc=1, partinc=1)[source]¶ Generator function returning the frontal elements.
This is a generator function and is normally not used directly, but via the
frontWalk()
method.Parameters: see
frontWalk()
.Returns: int array – Int array with a value for each element. On the initial call, all values are 1, except for the elements in the initial front, which get a value 0. At each call a new front is created with all the elements that are connected to any of the current front and which have not yet been visited. The new front elements get a value equal to the last front’s value plus the frontinc
. If the front becomes empty and a new starting front is created, the front value is extra incremented withpartinc
.Examples
>>> A = Adjacency([[ 1, 2,1], ... [ 3, 2, 0], ... [ 1,1, 3], ... [ 1, 2,1], ... [1,1,1]]) >>> for p in A.frontGenerator(): print(p) [ 0 1 1 1 1] [ 0 1 1 1 1] [ 0 1 1 2 1] [0 1 1 2 4]

frontWalk
(startat=0, frontinc=1, partinc=1, maxval=1)[source]¶ Walks through the elements by their node front.
A frontal walk is executed starting from the given element(s). A number of steps is executed, each step advancing the front over a given number of single pass increments. The step number at which an element is reached is recorded and returned.
Parameters:  startat (int or list of ints) – Initial element number(s) in the front.
 frontinc (int) – Increment for the front number on each frontal step.
 partinc (int) – Increment for the front number when the front gets empty and a new part is started.
 maxval (int) – Maximum frontal value. If negative (default) the walk will continue until all elements have been reached. If nonnegative, walking will stop as soon as the frontal value reaches this maximum.
Returns: int array – An array of ints specifying for each element in which step the element was reached by the walker.
Examples
>>> A = Adjacency([ ... [1, 1, 2, 3], ... [1, 0, 2, 3], ... [ 0, 1, 4, 5], ... [1, 1, 0, 1], ... [1, 1, 2, 5], ... [1, 1, 2, 4]]) >>> print(A.frontWalk()) [0 1 1 1 2 2]

front
(startat=0, add=False)[source]¶ Returns the elements of the first node front.
Parameters: Returns: int array – A list of the elements that are connected to any of the nodes that are part of the startat elements.
Notes
This is equivalent to the first step of a
frontWalk()
with the same startat elements, and could thus also be obtained fromwhere(self.frontWalk(startat,maxval=1) == 1)[0]
.Here however another implementation is used, which is more efficient for very large models: it avoids the creation of the large array as returned by frontWalk.
Examples
>>> a = Adjacency([[ 0, 0, 0, 1, 2, 5], ... [1, 0, 1, 1, 1, 3], ... [1, 1, 0, 1, 1, 2], ... [1, 1, 1, 1, 1, 3], ... [1, 1, 1, 1, 1, 1], ... [1, 1, 0, 1, 1, 5]]) >>> print(a.front()) [1 2 5] >>> print(a.front([0,1])) [2 3 5] >>> print(a.front([0,1],add=True)) [0 1 2 3 5]
 data (int array_like) – Data to initialize the Connectivity. The data should be 2dim with
shape