/*
 * CdbTuple.java
 *
 * Created on April 4, 2007, 8:37 AM
 *
 * Creates CDB tuple for addition to database.  Also
 * checks for constraint set satisfiability.
 */

package csce913proj1;
import java.io.Serializable;

/**
 *
 * @author John R. Hodges
 */
public class CdbTuple implements Serializable {
    
    
    /**
     * for serialization
     */
    private static final long serialVersionUID = -8537171694674323049L;
    
    /**
     * Represents an addition bound matrix
     */
    private ABMatrix abm;
    private ABMatrix posABM;
    private ABMatrix negABM;
    
    /**
     * names is a list of variable names associated with the rows and columns
     */
    private String[] names;
    
    /**
     * The do nothing constructor, you will probably want to write a do
     * something constructor.
     */
    public CdbTuple() {
        abm = null;
        posABM = null;
        negABM = null;
        names = null;
    }
    
    public CdbTuple(ABMatrix mat, ABMatrix posMat, ABMatrix negMat, String[] names) {
        abm = mat;
        posABM = posMat;
        negABM = negMat;
        this.names = names;
    }
    
    public boolean satisfiable() {
        double[][] matrix = abm.getMatrix();    // Difference matrix
        double[][] posMatrix = posABM.getMatrix();
        double[][] negMatrix = negABM.getMatrix();
        int n = abm.getM()-1;     // Size of the matrix
        double d;
        double dPrime;
        int x0 = 0;
        int y;
        int z;
        
        // Eliminate each Xn
        for (int x=n; x>0; x--) {
            // Case 1:  a=1, b=1, e=1
            // Rule 13
            d = matrix[x][x0];
            dPrime = matrix[x0][x];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = matrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = matrix[x0][x];
                if ((d + dPrime) < matrix[x0][y]) {
                    matrix[x0][y] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = posMatrix[y][x];
                if (((d + dPrime)/2) < matrix[x0][y]) {
                    matrix[x0][y] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = matrix[x][y];
                    dPrime = posMatrix[z][x];
                    if ((d + dPrime) < posMatrix[z][y]) {
                        posMatrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = matrix[x][y];
            dPrime = posMatrix[z][x];
            if ((d + dPrime) < posMatrix[z][y]) {
                posMatrix[z][y] = d + dPrime;
            }
            
            // Case 2:  a=1, b=1, e=-1
            // Rule 13
            d = matrix[x][x0];
            dPrime = matrix[x0][x];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = matrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = matrix[x0][x];
                if ((d + dPrime) < matrix[x0][y]) {
                    matrix[x0][y] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = matrix[x][y];
                dPrime = posMatrix[y][x];
                if (((d + dPrime)/2) < matrix[x0][y]) {
                    matrix[x0][y] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = matrix[x][y];
                    dPrime = matrix[z][x];
                    if ((d + dPrime) < matrix[z][y]) {
                        matrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = matrix[x][y];
            dPrime = matrix[z][x];
            if ((d + dPrime) < matrix[z][y]) {
                matrix[z][y] = d + dPrime;
            }
            
            // Case 3:  a=1, b=-1, e=1
            // Rule 13
            d = matrix[x][x0];
            dPrime = matrix[x0][x];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = posMatrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = matrix[x0][x];
                if ((d + dPrime) < matrix[y][x0]) {
                    matrix[y][x0] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = matrix[y][x];
                if (((d + dPrime)/2) < matrix[y][x0]) {
                    matrix[y][x0] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = negMatrix[y][x];
                    dPrime = posMatrix[z][x];
                    if ((d + dPrime) < matrix[y][z]) {
                        matrix[y][z] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = negMatrix[y][x];
            dPrime = posMatrix[z][x];
            if ((d + dPrime) < matrix[y][z]) {
                matrix[y][z] = d + dPrime;
            }
            
            // Case 4:  a=1, b=-1, e=-1
            // Rule 13
            d = matrix[x][x0];
            dPrime = matrix[x0][x];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = posMatrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = matrix[x0][x];
                if ((d + dPrime) < matrix[y][x0]) {
                    matrix[y][x0] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = negMatrix[y][x];
                dPrime = matrix[y][x];
                if (((d + dPrime)/2) < matrix[y][x0]) {
                    matrix[y][x0] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = negMatrix[y][x];
                    dPrime = matrix[z][x];
                    if ((d + dPrime) < negMatrix[z][y]) {
                        negMatrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = negMatrix[y][x];
            dPrime = matrix[z][x];
            if ((d + dPrime) < negMatrix[z][y]) {
                negMatrix[z][y] = d + dPrime;
            }
            
            // Case 5:  a=-1, b=1, e=1
            // Rule 13
            d = matrix[x0][x];
            dPrime = matrix[x][x0];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = negMatrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = matrix[x][x0];
                if ((d + dPrime) < matrix[x0][y]) {
                    matrix[x0][y] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = matrix[x][y];
                if (((d + dPrime)/2) < matrix[x0][y]) {
                    matrix[x0][y] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = posMatrix[y][x];
                    dPrime = matrix[x][z];
                    if ((d + dPrime) < posMatrix[z][y]) {
                        posMatrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = posMatrix[y][x];
            dPrime = matrix[x][z];
            if ((d + dPrime) < posMatrix[z][y]) {
                posMatrix[z][y] = d + dPrime;
            }
            
            // Case 6:  a=-1, b=1, e=-1
            // Rule 13
            d = matrix[x0][x];
            dPrime = matrix[x][x0];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = negMatrix[y][x];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = matrix[x][x0];
                if ((d + dPrime) < matrix[x0][y]) {
                    matrix[x0][y] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = posMatrix[y][x];
                dPrime = matrix[x][y];
                if (((d + dPrime)/2) < matrix[x0][y]) {
                    matrix[x0][y] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = posMatrix[y][x];
                    dPrime = negMatrix[z][x];
                    if ((d + dPrime) < matrix[z][y]) {
                        matrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = posMatrix[y][x];
            dPrime = negMatrix[z][x];
            if ((d + dPrime) < matrix[z][y]) {
                matrix[z][y] = d + dPrime;
            }
            
            // Case 7:  a=-1, b=-1, e=1
            // Rule 13
            d = matrix[x0][x];
            dPrime = matrix[x][x0];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = matrix[x][y];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = matrix[x][x0];
                if ((d + dPrime) < matrix[y][x0]) {
                    matrix[y][x0] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = negMatrix[y][x];
                if (((d + dPrime)/2) < matrix[y][x0]) {
                    matrix[y][x0] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = matrix[y][x];
                    dPrime = matrix[x][z];
                    if ((d + dPrime) < matrix[y][z]) {
                        matrix[y][z] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = matrix[y][x];
            dPrime = matrix[x][z];
            if ((d + dPrime) < matrix[y][z]) {
                matrix[y][z] = d + dPrime;
            }
            
            // Case 8:  a=-1, b=-1, e=-1
            // Rule 13
            d = matrix[x0][x];
            dPrime = matrix[x][x0];
            if ((d + dPrime) < matrix[x0][x0]) {
                matrix[x0][x0] = d + dPrime;
            }
            
            // Rule 14
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = matrix[x][y];
                if ((d + dPrime) < matrix[x0][x0]) {
                    matrix[x0][x0] = d + dPrime;
                }
            }
            
            // Rule 15
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = matrix[x][x0];
                if ((d + dPrime) < matrix[y][x0]) {
                    matrix[y][x0] = d + dPrime;
                }
            }
            
            // Rule 16
            for (y=n; y>0; y--) {
                d = matrix[y][x];
                dPrime = negMatrix[y][x];
                if (((d + dPrime)/2) < matrix[y][x0]) {
                    matrix[y][x0] = (d + dPrime)/2;
                }
            }
            
            // Rule 17
            for (y=n; y>1; y--) {
                for (z=n-1; z>0; z--) {
                    d = matrix[y][x];
                    dPrime = negMatrix[z][x];
                    if ((d + dPrime) < negMatrix[z][y]) {
                        negMatrix[z][y] = d + dPrime;
                    }
                }
            }
            y = 1;
            z = n;
            d = matrix[y][x];
            dPrime = matrix[x][z];
            if ((d + dPrime) < matrix[y][z]) {
                matrix[y][z] = d + dPrime;
            }
            
            for (int i=0; i<n; i++) {
                matrix[x][i] = Double.POSITIVE_INFINITY;
                matrix[i][x] = Double.POSITIVE_INFINITY;
            }
        }
        
        double result = matrix[x0][x0];
        if (result < 0) {
            return false;
        } else {
            return true;
        }
    }
}
