44. varray — Working with variable width tables.

Mesh type geometries use tables of integer data to store the connectivity between different geometric entities. The basic connectivity table in a Mesh with elements of the same type is a table of constant width: the number of nodes connected to each element is constant. However, the inverse table (the elements connected to each node) does not have a constant width.

Tables of constant width can conveniently be stored as a 2D array, allowing fast indexing by row and/or column number. A variable width table can be stored (using arrays) in two ways:

  • as a 2D array, with a width equal to the maximal row length. Unused positions in the row are then filled with an invalid value (-1).

  • as a 1D array, storing a simple concatenation of the rows. An additional array then stores the position in that array of the first element of each row.

In pyFormex, variable width tables were initially stored as 2D arrays: a remnant of the author’s past FORTRAN experience. With a growing professional use of pyFormex involving ever larger models, it became clear that there was a large memory and speed penalty related to the use of 2D arrays with lots of unused entries. This is illustrated in the following table, obtained on the inversion of a connectivity table of 10000 rows and 25 columns. The table shows the memory size of the inverse table, the time needed to compute it, and the time to compute both tables. The latter involves an extra conversion of the stored array to the other data type.

Stored as:

2D (ndarray)

1D (Varray)

1D (Varray)

Rows are sorted:

yes

yes

no

Memory size

450000

250000

250000

Time to create table

128 ms

49 ms

25ms

Time to create both

169 ms

82 ms

57ms

The memory and speed gains of using the Varray are important. The 2D array can even be faster generated by first creating the 1D array, and then converting that to 2D. Not sorting the entries in the Varray provides a further gain. The Varray class defined below therefore does not sort the rows by default, but provides methods to sort them when needed.

44.1. Classes defined in module varray

class varray.Varray(data=[], ind=None)[source]

A variable width 2D integer array

This class provides an efficient way to store tables of nonnegative integers when the rows of the table may have different length.

For large tables this may allow an important memory saving compared to a rectangular array where the non-existent entries are filled by some special value. Data in the Varray are stored as a single 1D array, containing the concatenation of all rows. An index is kept with the start position of each row in the 1D array.

Parameters
  • data

    Data to initialize to a new Varray object. This can either of:

    • another Varray instance: a shallow copy of the Varray is created.

    • a list of lists of integers. Each item in the list contains one row of the table.

    • a 2D ndarray of integer type. The nonnegative numbers on each row constitute the data for that row.

    • a 1D array or list of integers, containing the concatenation of the rows. The second argument ind specifies the indices of the first element of each row.

    • a 1D array or list of integers, containing the concatenation of the rows obtained by prepending each row with the row length. The caller should make sure these 1D data are consistent.

  • ind (1-dim int array_like, optional) – This is only used when data is a pure concatenation of all rows. It holds the position in data of the first element of each row. Its length is equal to the number of rows (nrows) or nrows+1. It is a non-decreasing series of integer values, starting with 0. If it has nrows+1 entries, the last value is equal to the total number of elements in data. This last value may be omitted, and will then be added automatically. Note that two subsequent elements may be equal, corresponding with an empty row.

Examples

Create a Varray from a nested list:

>>> Va = Varray([[0],[1,2],[0,2,4],[0,2]])
>>> Va
Varray([[0], [1, 2], [0, 2, 4], [0, 2]])

The Varray prints in a user-friendly format:

>>> print(Va)
Varray (4, (1, 3))
  [0]
  [1 2]
  [0 2 4]
  [0 2]

The internal data are 1-D arrays:

>>> print(Va.data)
[0 1 2 0 2 4 0 2]
>>> print(Va.ind)
[0 1 3 6 8]

Other initialization methods resulting in the same Varray:

>>> Vb = Varray(Va)
>>> print(str(Vb) == str(Va))
True
>>> Vb = Varray(np.array([[-1,-1,0],[-1,1,2],[0,2,4],[-1,0,2]]))
>>> print(str(Vb) == str(Va))
True
>>> Vc = Varray([0,1,2,0,2,4,0,2], at.cumsum0([1,2,3,2]))
>>> print(str(Vc) == str(Va))
True
>>> Vd = Varray([1,0, 2,1,2, 3,0,2,4, 2,0,2])
>>> print(str(Vd) == str(Va))
True

Show info about the Varray

>>> print(Va.nrows, Va.width, Va.shape)
4 (1, 3) (4, 3)
>>> print(Va.size, Va.lengths)
8 [1 2 3 2]

Indexing: The data for any row can be obtained by simple indexing:

>>> print(Va[1])
[1 2]

This is equivalent with

>>> print(Va.row(1))
[1 2]
>>> print(Va.row(-1))
[0 2]

Change elements:

>>> Va[1][0] = 3
>>> print(Va[1])
[3 2]

Full row can be changed with matching length:

>>> Va[1] = [1, 2]
>>> print(Va[1])
[1 2]

Negative indices are allowed:

Extracted columns are filled with -1 values where needed

>>> print(Va.col(1))
[-1  2  2  2]

Select takes multiple rows using indices or bool:

>>> print(Va.select([1,3]))
Varray (2, (2, 2))
  [1 2]
  [0 2]

>>> print(Va.select(Va.lengths==2))
Varray (2, (2, 2))
  [1 2]
  [0 2]

Iterator: A Varray provides its own iterator:

>>> for row in Va:
...     print(row)
[0]
[1 2]
[0 2 4]
[0 2]
>>> print(Varray())
Varray (0, (0, 0))

44.2. Functions defined in module varray

varray.graphColors(adj)[source]

Colorizes all nodes of a graph using Welsh-Powell algorithm.

The algorithm determines a color scheme thus that no two connected nodes of a graph have the same color. While not guaranteeing to be the optimal solution, it usually is a very close. This function can for example be used to determine a color scheme for different areas on a planar map, such that no two touching regions will have the same color.

Parameters

adj (varray_like) – An adjacency array where each row i lists the nodes connected to node i. It can be a Varray or a regular 2d array padded with -1 entries to have constant row length.

Returns

int array – An 1-d int array with the color palette numbers for the nodes.

Examples