[ 
https://issues.apache.org/jira/browse/MATH-1617?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ng Tsz Sum updated MATH-1617:
-----------------------------
    Description: 
>From 
>[https://stackoverflow.com/questions/68427448/how-to-find-the-inverse-of-a-matrix-using-apache-commons-math-library-in-java/68427869?noredirect=1#comment120932354_68427869]
h3. Reproducible example
{code:java}
import org.apache.commons.math3.linear.FieldLUDecomposition;
import org.apache.commons.math3.linear.FieldMatrix;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.util.BigReal;

public class REPREX {
    public static void main(String[] args) {
        BigReal[][] leftMatrixData = new BigReal[][]{
                {new BigReal(1), new BigReal(0), new BigReal(0), new 
BigReal(0)},
                {new BigReal(1), new BigReal(0), new BigReal(1), new 
BigReal(0)},
                {new BigReal(1), new BigReal(1), new BigReal(0), new 
BigReal(0)},
                {new BigReal(1), new BigReal(1), new BigReal(1), new 
BigReal(1)},
        };

        FieldMatrix<BigReal> leftMatrix = 
MatrixUtils.createFieldMatrix(leftMatrixData);
        FieldMatrix<BigReal> leftMatrixInverse = new 
FieldLUDecomposition<>(leftMatrix)
                .getSolver()
                .getInverse();
//  Exception in thread "main" 
org.apache.commons.math3.exception.MathArithmeticException: zero not allowed 
here
//        at org.apache.commons.math3.util.BigReal.divide(BigReal.java:255)
//        at org.apache.commons.math3.util.BigReal.divide(BigReal.java:39)
//        at 
org.apache.commons.math3.linear.FieldLUDecomposition.<init>(FieldLUDecomposition.java:160)
//        at stackoverflow.math.matrix.REPREX.main(REPREX.java:18)
    }
}
{code}
h3. Possible reason:

In {{FieldLUDecomposition}} line 130-133
{code:java}
                if (lu[nonZero][col].equals(field.getZero())) {
                    // try to select a better permutation choice
                    ++nonZero;
                }
{code}
Which produce incorrect result when {{lu[nonZeror][col]}} the BigDecimal val 
has different scale 
 to {{field.getZero()}} scale. as the {{BigReal#equals}} is comparing using 
{{BigDecimal#equals}}
h3. Workaround

I tried to copy class {{BigReal}} and {{BigRealField}} to {{FixBigReal}} and 
{{FixBigRealField}} and replace all {{BigReal}} to {{FixBigReal}} inside. Then 
override {{FixBIgReal#equals}} and {{FixBIgReal#hashcode }}as
{code:java}
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other instanceof FixBigReal) {
            return d.compareTo(((FixBigReal) other).d) == 0;
        }
        return false;
    }
...
    @Override
    public int hashCode() {
        return Double.hashCode(d.doubleValue());
    }
{code}
Then the below program will not throw error
{code:java}
import org.apache.commons.math3.linear.FieldLUDecomposition;
import org.apache.commons.math3.linear.FieldMatrix;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.util.BigReal;

public class MVE {
    public static void main(String[] args) {
        FixBigReal[][] leftMatrixData = new FixBigReal[][]{
                {new FixBigReal(1), new FixBigReal(0), new FixBigReal(0), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(0), new FixBigReal(1), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(1), new FixBigReal(0), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(1), new FixBigReal(1), new 
FixBigReal(1)},
        };

        FieldMatrix<FixBigReal> leftMatrix = 
MatrixUtils.createFieldMatrix(leftMatrixData);
        FieldMatrix<FixBigReal> leftMatrixInverse = new 
FieldLUDecomposition<>(leftMatrix)
                .getSolver()
                .getInverse();
    }
}
{code}

  was:
>From 
>[https://stackoverflow.com/questions/68427448/how-to-find-the-inverse-of-a-matrix-using-apache-commons-math-library-in-java/68427869?noredirect=1#comment120932354_68427869]

h3. Reproducible example

{code:java}
import org.apache.commons.math3.linear.FieldLUDecomposition;
import org.apache.commons.math3.linear.FieldMatrix;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.util.BigReal;

public class REPREX {
    public static void main(String[] args) {
        BigReal[][] leftMatrixData = new BigReal[][]{
                {new BigReal(1), new BigReal(0), new BigReal(0), new 
BigReal(0)},
                {new BigReal(1), new BigReal(0), new BigReal(1), new 
BigReal(0)},
                {new BigReal(1), new BigReal(1), new BigReal(0), new 
BigReal(0)},
                {new BigReal(1), new BigReal(1), new BigReal(1), new 
BigReal(1)},
        };

        FieldMatrix<BigReal> leftMatrix = 
MatrixUtils.createFieldMatrix(leftMatrixData);
        FieldMatrix<BigReal> leftMatrixInverse = new 
FieldLUDecomposition<>(leftMatrix)
                .getSolver()
                .getInverse();
//  Exception in thread "main" 
org.apache.commons.math3.exception.MathArithmeticException: zero not allowed 
here
//        at org.apache.commons.math3.util.BigReal.divide(BigReal.java:255)
//        at org.apache.commons.math3.util.BigReal.divide(BigReal.java:39)
//        at 
org.apache.commons.math3.linear.FieldLUDecomposition.<init>(FieldLUDecomposition.java:160)
//        at stackoverflow.math.matrix.REPREX.main(REPREX.java:18)
    }
}
{code}

h3. Possible reason:

In {{FieldLUDecomposition}} line 130-133
{code:java}
                if (lu[nonZero][col].equals(field.getZero())) {
                    // try to select a better permutation choice
                    ++nonZero;
                }
{code}
Which produce incorrect result when {{lu[nonZeror][col]}} the BigDecimal val 
has different scale 
to {{field.getZero()}} scale. as the {{BigReal#equals}} is comparing using 
{{BigDecimal#equals}}

h3. Workaround

I tried to copy class {{BigReal}} and {{BigRealField}} to {{FixBigReal}} and 
{{FixBigRealField}} and replace all {{BigReal}} to {{FixBigReal}} inside. Then 
override {{FixBIgReal#equals}} as 
{code:java}
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other instanceof FixBigReal) {
            return d.compareTo(((FixBigReal) other).d) == 0;
        }
        return false;
    }
{code}
Then the below program will not throw error
{code:java}
import org.apache.commons.math3.linear.FieldLUDecomposition;
import org.apache.commons.math3.linear.FieldMatrix;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.util.BigReal;

public class MVE {
    public static void main(String[] args) {
        FixBigReal[][] leftMatrixData = new FixBigReal[][]{
                {new FixBigReal(1), new FixBigReal(0), new FixBigReal(0), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(0), new FixBigReal(1), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(1), new FixBigReal(0), new 
FixBigReal(0)},
                {new FixBigReal(1), new FixBigReal(1), new FixBigReal(1), new 
FixBigReal(1)},
        };

        FieldMatrix<FixBigReal> leftMatrix = 
MatrixUtils.createFieldMatrix(leftMatrixData);
        FieldMatrix<FixBigReal> leftMatrixInverse = new 
FieldLUDecomposition<>(leftMatrix)
                .getSolver()
                .getInverse();
    }
}
{code}


> FieldLUDecomposition with BigReal throw divide by zero error
> ------------------------------------------------------------
>
>                 Key: MATH-1617
>                 URL: https://issues.apache.org/jira/browse/MATH-1617
>             Project: Commons Math
>          Issue Type: Bug
>    Affects Versions: 3.6.1
>            Reporter: Ng Tsz Sum
>            Priority: Major
>             Fix For: 4.0
>
>         Attachments: MATH-1617.patch
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> From 
> [https://stackoverflow.com/questions/68427448/how-to-find-the-inverse-of-a-matrix-using-apache-commons-math-library-in-java/68427869?noredirect=1#comment120932354_68427869]
> h3. Reproducible example
> {code:java}
> import org.apache.commons.math3.linear.FieldLUDecomposition;
> import org.apache.commons.math3.linear.FieldMatrix;
> import org.apache.commons.math3.linear.MatrixUtils;
> import org.apache.commons.math3.util.BigReal;
> public class REPREX {
>     public static void main(String[] args) {
>         BigReal[][] leftMatrixData = new BigReal[][]{
>                 {new BigReal(1), new BigReal(0), new BigReal(0), new 
> BigReal(0)},
>                 {new BigReal(1), new BigReal(0), new BigReal(1), new 
> BigReal(0)},
>                 {new BigReal(1), new BigReal(1), new BigReal(0), new 
> BigReal(0)},
>                 {new BigReal(1), new BigReal(1), new BigReal(1), new 
> BigReal(1)},
>         };
>         FieldMatrix<BigReal> leftMatrix = 
> MatrixUtils.createFieldMatrix(leftMatrixData);
>         FieldMatrix<BigReal> leftMatrixInverse = new 
> FieldLUDecomposition<>(leftMatrix)
>                 .getSolver()
>                 .getInverse();
> //  Exception in thread "main" 
> org.apache.commons.math3.exception.MathArithmeticException: zero not allowed 
> here
> //      at org.apache.commons.math3.util.BigReal.divide(BigReal.java:255)
> //      at org.apache.commons.math3.util.BigReal.divide(BigReal.java:39)
> //      at 
> org.apache.commons.math3.linear.FieldLUDecomposition.<init>(FieldLUDecomposition.java:160)
> //      at stackoverflow.math.matrix.REPREX.main(REPREX.java:18)
>     }
> }
> {code}
> h3. Possible reason:
> In {{FieldLUDecomposition}} line 130-133
> {code:java}
>                 if (lu[nonZero][col].equals(field.getZero())) {
>                     // try to select a better permutation choice
>                     ++nonZero;
>                 }
> {code}
> Which produce incorrect result when {{lu[nonZeror][col]}} the BigDecimal val 
> has different scale 
>  to {{field.getZero()}} scale. as the {{BigReal#equals}} is comparing using 
> {{BigDecimal#equals}}
> h3. Workaround
> I tried to copy class {{BigReal}} and {{BigRealField}} to {{FixBigReal}} and 
> {{FixBigRealField}} and replace all {{BigReal}} to {{FixBigReal}} inside. 
> Then override {{FixBIgReal#equals}} and {{FixBIgReal#hashcode }}as
> {code:java}
>     @Override
>     public boolean equals(Object other) {
>         if (this == other) {
>             return true;
>         }
>         if (other instanceof FixBigReal) {
>             return d.compareTo(((FixBigReal) other).d) == 0;
>         }
>         return false;
>     }
> ...
>     @Override
>     public int hashCode() {
>         return Double.hashCode(d.doubleValue());
>     }
> {code}
> Then the below program will not throw error
> {code:java}
> import org.apache.commons.math3.linear.FieldLUDecomposition;
> import org.apache.commons.math3.linear.FieldMatrix;
> import org.apache.commons.math3.linear.MatrixUtils;
> import org.apache.commons.math3.util.BigReal;
> public class MVE {
>     public static void main(String[] args) {
>         FixBigReal[][] leftMatrixData = new FixBigReal[][]{
>                 {new FixBigReal(1), new FixBigReal(0), new FixBigReal(0), new 
> FixBigReal(0)},
>                 {new FixBigReal(1), new FixBigReal(0), new FixBigReal(1), new 
> FixBigReal(0)},
>                 {new FixBigReal(1), new FixBigReal(1), new FixBigReal(0), new 
> FixBigReal(0)},
>                 {new FixBigReal(1), new FixBigReal(1), new FixBigReal(1), new 
> FixBigReal(1)},
>         };
>         FieldMatrix<FixBigReal> leftMatrix = 
> MatrixUtils.createFieldMatrix(leftMatrixData);
>         FieldMatrix<FixBigReal> leftMatrixInverse = new 
> FieldLUDecomposition<>(leftMatrix)
>                 .getSolver()
>                 .getInverse();
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to