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