Creating new vector types in TiPi

For now TiPi only provides two concrete types of vectors, DoubleShapedVector and FlaotShapedVector, with their respective vector spaces classes, DoubleShapedVectorSpace and FloatShapedVectorSpace. Such vectors store their components in a single Java array of type double[] or float[] and are closely connected to ShapedArray (i.e., they also have a shape). For very large problems, it may be more convenient to store the components of the vectors differently, perhaps on different machines and/or in GPU memory. It is possible (and hopefully easy) to make TiPi aware of this specific storage by implementing the corresponding vector and vector space classes. Another reason to create a new vector and vector space type may be to provide more efficient (e.g., multi-threaded) versions of the methods designed to operate on vectors.

Implementing a new type of vectors in TiPi involves two things:

  1. A concrete sub-class of Vector for the vectors of this vector space. This can be as simple as implementing the two methods get() and set() for getting and setting a specific component of a vector. These methods are not meant to be efficient, they are mainly provided for testing or debugging purposes.

  2. A concrete sub-class of VectorSpace for the vector space. Only a dozen of methods which operate on the specifc vectors of this vector space have to be implemented. These methods are assumed to be efficient and are used by TiPi to perform all necessary operations on vectors.

All methods whose name begins with an underscore character, e.g. _dot, are low-level protected methods which must not be directly called by the end-user. They are used by higher level methods which take care of checking the validity of the arguments, in particular that the vectors belong to the correct vector space. Thus in the implementation of these low level methods no argument checking is necessary.

Even though vectors can use any type of floating point values to store their components, all scalar values in TiPi are passed as double precision floating point.

Methods that must be overridden

A concrete implementation of the Vector class has to override the following methods:

As said before, these two methods are not meant to be efficient, they are mainly provided for testing or debugging purposes. This is not the case for the methods of the concrete implementation of the VectorSpace class described below.

A concrete implementation of the VectorSpace class has to override the following mandatory methods:

Methods with default implementation

The following methods have a default implementation which can be overridden with more efficient versions by the descendants of the VectorSpace abstract class:

protected double _norm2(Vector x) {
    return Math.sqrt(_dot(x, x));
}
protected void _scale(Vector vec, double alpha) {
    _scale(vec, alpha, vec);
}
protected void _copy(Vector dst, Vector src) {
    _combine(dst, 1, src, 0, src);
}
protected Vector _clone(Vector vec) {
    Vector cpy = create();
    _copy(cpy, vec);
    return cpy;
}
protected void _zero(Vector vec) {
    _fill(vec, 0);
}
protected void _add(Vector dst, double alpha, Vector x) {
    _combine(dst, 1, dst, alpha, x);
}