001/* 002 * $Id: FactorFraction.java 5658 2016-12-24 16:11:29Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.SortedMap; 011import java.util.TreeMap; 012import java.util.Map; 013 014import org.apache.log4j.Logger; 015 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.structure.GcdRingElem; 019import edu.jas.structure.RingElem; 020import edu.jas.structure.RingFactory; 021import edu.jas.structure.QuotPair; 022import edu.jas.structure.QuotPairFactory; 023 024 025/** 026 * Fraction factorization algorithms. This class implements 027 * factorization methods for fractions represended as pairs of 028 * polynomials. 029 * @author Heinz Kredel 030 */ 031 032public class FactorFraction<C extends GcdRingElem<C>, 033 D extends GcdRingElem<D> & QuotPair<GenPolynomial<C>> > { 034 035 036 private static final Logger logger = Logger.getLogger(FactorFraction.class); 037 038 039 /** 040 * Quotient pairs ring factory. 041 * D == QuotPair<GenPolynomial<C>> must hold. 042 */ 043 protected final QuotPairFactory<GenPolynomial<C>, D> qfac; 044 045 046 /** 047 * Factorization engine for normal coefficients. 048 */ 049 protected final FactorAbstract<C> nengine; 050 051 052 /** 053 * No argument constructor. 054 */ 055 protected FactorFraction() { 056 throw new IllegalArgumentException("don't use this constructor"); 057 } 058 059 060 /** 061 * Constructor. 062 * @param fac coefficient quotient ring factory. 063 */ 064 public FactorFraction(QuotPairFactory<GenPolynomial<C>,D> fac) { 065 this(fac, FactorFactory.<C> getImplementation(((GenPolynomialRing<C>) fac.pairFactory()).coFac)); 066 } 067 068 069 /** 070 * Constructor. 071 * @param fac coefficient quotient ring factory. 072 * @param nengine factorization engine for polynomials over base 073 * coefficients. 074 */ 075 public FactorFraction(QuotPairFactory<GenPolynomial<C>,D> fac, FactorAbstract<C> nengine) { 076 this.qfac = fac; 077 this.nengine = nengine; 078 logger.info("qfac.fac: " + qfac.pairFactory().toScript()); 079 } 080 081 082 /** 083 * Get the String representation. 084 * @see java.lang.Object#toString() 085 */ 086 @Override 087 public String toString() { 088 return getClass().getName(); 089 } 090 091 092 /** 093 * Test if a quotient pair is irreducible. 094 * @param P quotient pair (num,den), with gcd(num,den) == 1. 095 * @return true if P is irreducible, else false. 096 */ 097 public boolean isIrreducible(D P) { 098 SortedMap<D, Long> F = factors(P); 099 for (Long e : F.values()) { 100 if (e == null || e != 1L) { 101 return false; 102 } 103 } 104 if (F.size() <= 1) { // x/1 105 return true; 106 } else if (F.size() == 2) { // x/1, 1/y 107 List<D> pp = new ArrayList<D>( F.keySet() ); 108 D f = pp.get(0); 109 D g = pp.get(1); 110 if ((f.numerator().isONE() && g.denominator().isONE()) || (g.numerator().isONE() && f.denominator().isONE())) { 111 return true; 112 } 113 return false; 114 } else if (F.size() > 2) { 115 return false; 116 } 117 return false; 118 } 119 120 121 /** 122 * Test if a non trivial factorization exsists. 123 * @param P quotient pair (num,den), with gcd(num,den) == 1. 124 * @return true if P is reducible, else false. 125 */ 126 public boolean isReducible(D P) { 127 return !isIrreducible(P); 128 } 129 130 131 /** 132 * Quotient pair factorization. 133 * @param P quotient pair (num,den), with gcd(num,den) == 1. 134 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i**e_i. 135 */ 136 public SortedMap<D, Long> factors(D P) { 137 // D == QuotPair<GenPolynomial<C>> 138 SortedMap<D, Long> facs = new TreeMap<D, Long>(); 139 if (P == null) { 140 return facs; 141 } 142 GenPolynomial<C> n = P.numerator(); 143 GenPolynomial<C> d = P.denominator(); 144 if (n.isZERO() || d.isZERO()) { 145 return facs; 146 } 147 if (n.isONE() && d.isONE()) { 148 facs.put(P,1L); 149 return facs; 150 } 151 // assert gcd(n,d) == 1 152 GenPolynomial<C> one = qfac.pairFactory().getONE(); 153 if (!n.isONE()) { 154 SortedMap<GenPolynomial<C>, Long> nfacs = nengine.factors(n); 155 for (Map.Entry<GenPolynomial<C>,Long> m : nfacs.entrySet()) { 156 D q = qfac.create(m.getKey(), one); 157 facs.put(q, m.getValue()); 158 } 159 } 160 if (!d.isONE()) { 161 SortedMap<GenPolynomial<C>, Long> dfacs = nengine.factors(d); 162 for (Map.Entry<GenPolynomial<C>,Long> m : dfacs.entrySet()) { 163 D q = qfac.create(one, m.getKey()); 164 facs.put(q, m.getValue()); 165 } 166 } 167 return facs; 168 } 169 170 171 /** 172 * Test quotient pair factorization. 173 * @param P quotient pair. 174 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 175 * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. 176 */ 177 public boolean isFactorization(D P, SortedMap<D, Long> F) { 178 if (P == null || F == null) { 179 throw new IllegalArgumentException("P and F may not be null"); 180 } 181 if (P.isZERO() && F.size() == 0) { 182 return true; 183 } 184 D t = null; //P.ring.getONE(); 185 for (Map.Entry<D, Long> me : F.entrySet()) { 186 D f = me.getKey(); 187 Long E = me.getValue(); 188 long e = E.longValue(); 189 D g = f.power(e); 190 if (t == null) { 191 t = g; 192 } else { 193 t = t.multiply(g); 194 } 195 } 196 boolean f = P.equals(t) || P.equals(t.negate()); 197 if (!f) { 198 System.out.println("\nfactorization(map): " + f); 199 System.out.println("F = " + F); 200 System.out.println("P = " + P); 201 System.out.println("t = " + t); 202 //RuntimeException e = new RuntimeException("fac-map"); 203 //e.printStackTrace(); 204 //throw e; 205 } 206 return f; 207 } 208 209}