roel
roel

Reputation: 109

Defining abstract math with java

I am trying to define some basic mathematical concepts in java, but keep getting stuck with generics errors. Consider the example below. In this example, I try to define the zero mapping (f(x) = 0 for all x) as both a constant mapping (f(x) = c for all x), and a linear mapping (f(a*x + b*y) = a*f(x) + b*f(y)). The compiler doesn't let me do that because the statement 'the zero mapping is a vector' is ambiguous (in terms of java, but not mathematically).

Can you suggest a clean solution to this problem?

// A vector in a finite-dimensional vector space over the real numbers.
interface Vector<V extends Vector<?>>
{
    int dimension();
    V plus(V v);
    V times(double c);
}

interface Mapping<U extends Vector<?>, V extends Vector<?>>
// Does not inherit from Vector because the set of all mappings is an
// infinite-dimensional vector space.
{
    V map(U u);
}

// Linear mappings, on the other hand, from one finite-dimensional vector space
// to another, do form a finite-dimensional vector space.
interface LinearMapping<U extends Vector<?>, V extends Vector<?>>
    extends Mapping<U, V>, Vector<LinearMapping<U, V>>
{
}

// All elements of U are mapped to getImage(). If V is finite-dimensional, then
// the set of constant mappings is also a finite-dimensional vector space.
interface ConstMapping<U extends Vector<?>, V extends Vector<?>>
    extends Mapping<U, V>, Vector<ConstMapping<U, V>>
{
    V getImage();
}

// A zero mapping is both constant and linear, but cannot be defined as such.
interface ZeroMapping<U extends Vector<?>, V extends Vector<?>>
    extends LinearMapping<U, V>, ConstMapping<U, V>
// Error: The interface Vector cannot be implemented more than once with
// different arguments: Vector<ConstMapping<U,V>> and Vector<LinearMapping<U,V>>
{
}

Upvotes: 4

Views: 255

Answers (1)

nitegazer2003
nitegazer2003

Reputation: 1193

The issue seems to be that ZeroMapping is extending both Vector<LinearMapping> and Vector<ConstMapping>.

To fix that, we change the generic parameter V of LinearMapping and ConstMapping to the lower bounds of their individual classes, so that they can extend the generic Vector<V>, allowing for more flexibility. Hopefully this captures your intention of making LinearMapping both a Mapping and a Vector (of itself, only).

EDIT: in that case, you may have to go with 3 generic parameters: 2 to capture the "Mapping" and 1 to capture the "Vector" relation with other LinearMappings of the same type.

ZeroMapping then follows the same format.

I've included @LuiggiMendoza 's suggestion in the response below.

interface Vector<V extends Vector<V>>
{
    int dimension();
    V plus(V v);
    V times(double c);
}

interface Mapping<U extends Vector<U>, V extends Vector<V>>
// Does not inherit from Vector because the set of all mappings is an
// infinite-dimensional vector space.
{
    V map(U u);
}

// Linear mappings, on the other hand, from one finite-dimensional vector space
// to another, do form a finite-dimenszional vector space.
interface LinearMapping<U extends Vector<U>, V extends Vector<V>, W extends LinearMapping<U, V, W>>
    extends Mapping<U, V>, Vector<W>
{
}

// All elements of U are mapped to getImage(). If V is finite-dimensional, then
// the set of constant mappings is also a finite-dimensional vector space.
interface ConstMapping<U extends Vector<U>, V extends Vector<V>, W extends ConstMapping<U, V, W>>
    extends Mapping<U, V>, Vector<W>
{
    V getImage();
}

// A zero mapping is both constant and linear, but cannot be defined as such.
interface ZeroMapping<U extends Vector<U>, V extends Vector<V>, W extends ZeroMapping<U, V, W>>
    extends LinearMapping<U, V, W>, ConstMapping<U, V, W>
{
}

An example of how the class would be implemented could be:

class RealVector implements Vector<RealVector> { // methods here .. // }

class RealLinearMapping implements LinearMapping<RealVector, RealVector, RealLinearMapping>
{
    @Override
    public RealVector map(RealVector u) { ... }

    @Override
    public RealLinearMapping plus(RealLinearMapping v) { ... }
}

Upvotes: 3

Related Questions