- JavaDoc

# JEP

- Introduction
- Basic Usage
- Variables
- Data types
- Operators
- Functions
- BigDecimal
- Manipulating Expressions
- Components
- Configurable Parser
- Grammar
- FAQ
- Migration
- Version History

# GroupJep - Exact arithmetic over the integers, rationals and other groups

The org.lsmp.djep.groupJep package offers:

- Exact arithmetic for the integers and rationals
- A framework for allowing arbitrary groups, rings and fields to be used
- Implementation of several groups: integers mod n, free groups, finite field extensions (allowing the use of algebraic numbers)

This package is primarily a bit of a play thing, allowing the JEP parser and evaluator to be used with arbitrary groups. It should not be treated as a substitute for a dedicated computer algebra package but it does allow a bit of experimentation with different groups rings and fields.

An interactive console applet interactive console applet illustrates the functionality of GroupJep.

## Basic usage

The GroupJep package is relatively easy to use, all the standard JEP features are enabled. To create a version of JEP for a particular group the GroupJep(GroupI group) constructor should be called where the argument is the specification of a certain group. For example to work of arbitrary precision integers to calculate factorial 20 use:

    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.groups.*;

    JEP j = new GroupJep(new Integers());
    Node node = j.parse("1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20");
    Object value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 2432902008176640000

A number of predefined groups are provided. These are all found in the org.lsmp.djep.groupJep.groups package.

- Integers: arbitrary precision integers, implement as java.math.BigInteger.
- Rationals: arbitrary precision rational numbers: implemented as a quotient of BigInteger's.
- Reals: real numbers implemented as double.
- BigReals: real numbers implemented as either BigDecimals.
- Zn: integers mod n.
- FreeGroup: the free group with one generator, elements a_n t^n + ...+ a_1 t + a_0.
- AlgebraicExtension: a group extended by an algebraic number. Allows exact computation using algebraic numbers.

Examples of the use of these groups:

    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.groups.*;

    class GroupExamples {
    public static void main(String args[])
    {
    JEP j = new GroupJep(new Integers());
    Node node = j.parse("1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20");
    Object value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 2432902008176640000

    j =  new GroupJep(new Rationals());
    node = j.parse("(1/2)-(1/3)");
    value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 1/6

    j = new GroupJep(new Zn(BigInteger.valueOf(5)));
    node = j.parse("3+3");
    value = j.evaluate(node);
    System.out.println(value.toString()); // prints 1

    node = j.parse("3*3");
    value = j.evaluate(node);
    System.out.println(value.toString()); // prints 4

### Free groups/Polynomials

Any ring can be extended to form a FreeGroup with a single generator. In effect this allows JEP to function with polynomials as a basic type and they will always be reduced to their basic type.

To use:

    import org.lsmp.djep.groupJep.interfaces.*;
    import org.lsmp.djep.groupJep.*;
    ...
    RingI ring = new Integers();
    RingI freeGroup = new FreeGroup(ring,"t");
    JEP j = new GroupJep(freeGroup);
    // this line is needed to ensure the parser recognises the symbol t
    j.addStandardConstants();

    Node node = j.parse("(t + 2)*(t+4)");
    Object value = j.evaluate(node);
    System.out.println(value.toString()); // prints t^2+5 t+6

Note that the addStandardConstants method of JEP must be called to ensure that the variable t is added to the parser. Free groups with more than one generator can be constructed by repeatedly extending a ring:

    RingI freeGroup = new FreeGroup(new FreeGroup(new Integers(),"t"),"s");

Polynomials in multiple variables can be defined by repeatidly extending.

    RingI ring = new Reals();
    FreeGroup fg = new ExtendedFreeGroup(ring,"x");
    FreeGroup fg2 = new ExtendedFreeGroup(fg,"y");
    j = new GroupJep(fg2);
    j.addStandardConstants();
    j.setAllowAssignment(true);
    j.setAllowUndeclared(true);
    Node n2 = j.parse("(x+1)*(y-2)");
    FreeGroupElement fge = (FreeGroupElement) j.evaluate(n2);

The coefficients of the polynomial can be found using:

    Number co1[] = fge.getCoeffs();
    for(int i=0;i<co1.length;++i)
    {
    	FreeGroupElement fge3 = (FreeGroupElement) co1[i];
    	Number co2[] = fge3.getCoeffs();
    	for(int j=0;j<co2.length;++j)
    		System.out.print(co2[j]+"\t");
    	System.out.println();
    }

To calculate

    fg.setRootVal(new Complex(5.0));
    fg2.setRootVal(new Complex(4.0));
    System.out.println(fge2.toString());
    Complex val = fge2.getComplexValue();

### Algebraic Numbers

In a similar fashion a ring can be extended by an algebraic number t to form an AlgebraicExtension. The algebraic number is defined to be a root of a Polynomial equation with coefficients in the base ring.

    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.interfaces.*;
    import org.lsmp.djep.groupJep.groups.*;
    import org.lsmp.djep.groupJep.values.*;
    ...
    RingI ring = new Integers();
    // specify the polynomial 1 x^2 + 0 x -2
    Number coeffs[] = new Number[]{
    			BigInteger.valueOf(-2),
    			BigInteger.ZERO,
    			BigInteger.ONE};
    Polynomial p1 = new Polynomial(ring,"rt2",coeffs);

    j = new GroupJep(new AlgebraicExtension(ring, p1));
    j.addStandardConstants();

    Node node = j.parse("(t+1)*(t+1)");
    Object value = j.evaluate(node);
    System.out.println(value.toString()); // prints 2 t+3
    System.out.println(((HasComplexValueI) value).getComplexValue());
    	// prints (5.82842712474619, 0.0)

Note in the last line the values can be converted to approximate complex numbers (in the group constructor if the polynomial is quadratic or an n-th root then an approximation to the complex value of a solution is calculate. The value returned by j.evaluate will be an object of type AlgebraicExtensionElement which implements org.lsmp.djep.groupJep.values.HasComplexValueI by providing a getComplexValue() method. This method will use the approximate value of the root to calculate the complex value of this element.

### Creating your own groups

Creating a group class is fairly straight forward. The class must implement org.lsmp.djep.groupJep.GroupI or one of the other interfaces in the org.lsmp.djep.groupJep.interfaces package which give extra properties such as RingI, FieldI. Typically the group will subclass org.lsmp.djep.groupJep.groups.Group which provides a few default methods. All groups should provide the methods:

    public Number getZERO();
    public Number getInverse(Number num);
    public Number add(Number a,Number b);
    public Number sub(Number a,Number b);
    public boolean equals(Number a,Number b);
    public Number valueOf(String s);

The different interfaces available and the methods they define are:

Interface | Methods
--- | ---
GroupI | public Number getZERO(); public Number getInverse(Number num); public Number add(Number a,Number b); public Number sub(Number a,Number b); public boolean equals(Number a,Number b); public Number valueOf(String s);
AbelianGroupI | Same methods as GroupI. implies group is commutative under +.
RingI | Methods for GroupI plus:- public Number getONE(); public Number mul(Number a,Number b); public Number getMulInverse(Number num);
IntegralDomainI | Same methods as RingI. This interface implies the group has: an identity for multiplication *; it is commutative under * and that cancellation is meaningful (if a is not 0 then a*b = a*c implies b = c).
HasDivI | Group has some notion of division i.e. integers public Number div(Number a,Number b);
FieldI | Same methods as for RingI plus public Number div(Number a,Number b);
HasModI | The modulus function is defined: public Number mod(Number a,Number b);
HasPowerI | The power function is defined: public Number pow(Number a,Number b);
OrderedSetI | There is a natural ordering to the set so <, <=, >, >= are meaningful. public int compare(Number a,Number b); will return -1 if a<b, 0 if a=b, +1 if a>b.
HasListI | List operations i.e. [a,b,c] is meaningful. public Number list(Number eles[]);