The Java classes defined in this package implement basic
two-dimensional linear algebra in the form of a collection of
operations defined on a Matrix class represented as a 2D
array of doubles. (Follow the link for a short, interesting,
entertaining, and informative, presentation on the origins and
history of Matrix
Algebra).
Organization of the algebra classes
The arithmetic on double matrix entries is generic. It is
generic because all matrix-algebra operations (matrix plus,
unary and binary matrix minus, matrix times,
etc.), are expressed in terms of the operations of an abstract
NumberAlgebra defining the
following number operations on double entries:
double zero()
: constant of type double;
double one()
: constant of type double;
double sum(double,double)
: addition operation on doubles;
double product(double,double)
: multiplication operation on doubles;
double negation(double)
: negation operation on a double;
double difference(double,double)
: difference operation on doubles.
More operations on number entries could be defined depending on the
nature of specific subclasses of a NumberAlgebra
(e.g., divide, inverse, quasi-inverse,
etc.). Therefore, these six operations are a required minimum
set. More operations defined on numbers allow then more operations to
be defined on matrices (e.g., matrix entry pivoting, matrix
inversion, linear equation solving, simplex, graph-path operations,
etc.). Therefore, the hlt.math.matrix package is
expected to grow as more capabilities are supported.
In this way, all the matrix operations are thus parameterized with
respect to any concrete subclass of NumberAlgebra algebra implementing
these methods for the values making up matrix of double
entries.
It also defines two concrete such subclasses.
StandardAlgebra
defining:
zero() ≝ 0.0;
one() ≝ 1.0;
sum(x,y) ≝ x+y;
product(x,y) ≝ x*y;
negation(x) ≝ -x;
difference(x,y) ≝ x-y;
MaxMinAlgebra defining:
zero() ≝ Double.NEGATIVE_INFINITY;
one() ≝ Double.POSITIVE_INFINITY;
sum(x,y) ≝ Math.max(x,y);
product(x,y) ≝ Math.min(x,y);
negation(x) is undefined;
difference(x,y) is undefined.
We will also define the following abstract subclass of NumberAlgebra to be used for
defining fuzzy operations:
FuzzyAlgebra with default
operations:
zero() ≝ 0.0;
one() ≝ 1.0;
sum(x,y) ≝ Math.max(x,y);
product(x,y) ≝ Math.min(x,y);
negation(x) ≝ one()-x;
difference(x,y) ≝ sum(x,negation(y)).
Importantly, the class FuzzyAlgebra is
abstract because it defines the sum and product
operations as abstract methods. It has three concrete subclasses
defined defined in the current hlt.math.fuzzy
package: (1) the class hlt.math.fuzzy.ZadehAlgebra,
(2) the class hlt.math.fuzzy.ProbabilisticAlgebra,
and the class (3) hlt.math.fuzzy.LukasieviczAlgebra.
The class ZadehAlgebra is the fuzzy algebra the most
commonly known and used. It is the fuzzy algebra defined in
Lotfi Zadeh's 1965 paper. This class inherits all the defaults
defined in its abstract FuzzyAlgebra
superclass.
The class ProbabilisticAlgebra inherits all methods, except
sum and product that are defined as:
sum(x,y) ≝ x+y-x*y;
product(x,y) ≝ x*y;
The class LukasieviczAlgebra inherits all methods, except
sum and product that are defined as:
sum(x,y) ≝ Math.min(x+y,1.0);
product(x,y) ≝ Math.max(0.0,x+y-1.0).
To be well-defined, methods implementing a fuzzy algebra's operations
should obey at least the following axioms, for any double
x:
sum(x,zero()) = sum(zero(),x) = x;
product(x,zero()) = product(zero(),x) = zero().
product(x,one()) = product(one(),x) = x;
These look familiar as they do hold in standard arithmetic. But what
about:
sum(x,one()) = sum(one(),x) = one()?
While this obviously does not hold for the StandardAlgebra defing
standard number arithmetic (since it is not true that x+1 =
1 or 1+x = 1, for any x), it does
hold in many algebras such as MaxMinAlgebra or FuzzyAlgebra at its
subclasses, in addition to the three axioms above.
It is important to understand the justification for making the same
number-entry algebra be the value of a static component of the class
NumberAlgebra to be shared by
all matrix operations unless redefined explicitly by a NumberAlgebra static class
method. Proceeding otherwise (i.e., allowing each matrix to
carry its own algebra) is both inefficient and opens the door to
inconsistencies that can only be avoided by using mostly useless
checks. Using only one unique number algebra in effect for any matrix
operations at a given a time solves the issue. For example, if the
current algebra set to be in effect in the class NumberAlgebra is MaxMinAlgebra, all matrix
operations will implicitly use the operations of a MaxMinAlgebra for its operations on
the double entries.
Therefore, one must be aware that if some computation in the same
application requires, say, both StandardAlgebra and MaxMinAlgebra matrix operations,
the only safe and consistent way to proceed is to reset the value of
the static algebra in NumberAlgebra to the necessary
algebra, which will not change until the next such explicit
invocation of the class method:
NumberAlgebra.setCurrentAlgebra(NumberAlgebra.maxMinAlgebra());
until its is set to another explicit algebra setting; say:
NumberAlgebra.setCurrentAlgebra(NumberAlgebra.standardAlgebra());
or more succinctly, with the equivalent:
NumberAlgebra.setMaxMinAlgebra());
and:
NumberAlgebra.setStandardAlgebra();
provided shorthand class methods.
|