001/* 002 * $Id: PolyModUtil.java 5611 2016-10-03 22:06:32Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.gb.SolvableGroebnerBaseAbstract; 014import edu.jas.gb.SolvableGroebnerBaseSeq; 015import edu.jas.poly.GenPolynomial; 016import edu.jas.poly.GenPolynomialRing; 017import edu.jas.poly.GenSolvablePolynomial; 018import edu.jas.poly.GenSolvablePolynomialRing; 019import edu.jas.poly.PolyUtil; 020import edu.jas.structure.GcdRingElem; 021 022 023/** 024 * Package gb and gbufd utilities. 025 * @author Heinz Kredel 026 */ 027 028public class PolyModUtil { 029 030 031 private static final Logger logger = Logger.getLogger(PolyModUtil.class); 032 033 034 private static final boolean debug = logger.isDebugEnabled(); 035 036 037 /** 038 * Least common multiple via ideal intersection. 039 * @param r solvable polynomial ring. 040 * @param n first solvable polynomial. 041 * @param d second solvable polynomial. 042 * @return lcm(n,d) 043 */ 044 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzLcm(GenSolvablePolynomialRing<C> r, 045 GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 046 if (n.isZERO()) { 047 return n; 048 } 049 if (d.isZERO()) { 050 return d; 051 } 052 if (n.isONE()) { 053 return d; 054 } 055 if (d.isONE()) { 056 return n; 057 } 058 List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(1); 059 A.add(n); 060 List<GenSolvablePolynomial<C>> B = new ArrayList<GenSolvablePolynomial<C>>(1); 061 B.add(d); 062 List<GenSolvablePolynomial<C>> c = PolyGBUtil.<C> intersect(r, A, B); 063 //if (c.size() != 1) { 064 // SolvableSyzygyAbstract<C> sz = new SolvableSyzygyAbstract<C>(); 065 // GenSolvablePolynomial<C>[] oc = sz.leftOreCond(n,d); 066 // GenSolvablePolynomial<C> nc = oc[0].multiply(n); 067 // System.out.println("nc = " + nc); 068 // return nc; 069 //} 070 GenSolvablePolynomial<C> lcm = null; 071 for (GenSolvablePolynomial<C> p : c) { 072 if (p == null || p.isZERO()) { 073 continue; 074 } 075 //System.out.println("p = " + p); 076 if (lcm == null) { 077 lcm = p; 078 continue; 079 } 080 if (lcm.compareTo(p) > 0) { 081 lcm = p; 082 } 083 } 084 if (lcm == null) { 085 throw new RuntimeException("this cannot happen: lcm == null: " + c); 086 } 087 return lcm; 088 } 089 090 091 /** 092 * Greatest common divisor via least common multiple. 093 * @param r solvable polynomial ring. 094 * @param n first solvable polynomial. 095 * @param d second solvable polynomial. 096 * @return gcd(n,d) 097 */ 098 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzGcd(GenSolvablePolynomialRing<C> r, 099 GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 100 return syzLeftGcd(r, n, d); 101 } 102 103 104 /** 105 * Left greatest common divisor via least common multiple. 106 * @param r solvable polynomial ring. 107 * @param n first solvable polynomial. 108 * @param d second solvable polynomial. 109 * @return gcd(n,d) 110 */ 111 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzLeftGcd( 112 GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 113 114 if (n.isZERO()) { 115 return d; 116 } 117 if (d.isZERO()) { 118 return n; 119 } 120 if (n.isConstant()) { 121 return r.getONE(); 122 } 123 if (d.isConstant()) { 124 return r.getONE(); 125 } 126 if (n.totalDegree() > 3 || d.totalDegree() > 3) { // how avoid too long running GBs ? 127 //if (n.totalDegree() + d.totalDegree() > 6) { // how avoid too long running GBs ? 128 // && n.length() < 10 && d.length() < 10 129 logger.warn("skipping GB computation: degs = " + n.totalDegree() + ", " + d.totalDegree()); 130 return r.getONE(); 131 } 132 List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(2); 133 A.add(n); 134 A.add(d); 135 SolvableGroebnerBaseAbstract<C> sbb = new SolvableGroebnerBaseSeq<C>(); 136 logger.warn("left syzGcd computing GB: " + A); 137 List<GenSolvablePolynomial<C>> G = sbb.rightGB(A); //not: leftGB, not: sbb.twosidedGB(A); 138 if (debug) { 139 logger.info("G = " + G); 140 } 141 if (G.size() == 1) { 142 return G.get(0); 143 } 144 logger.warn("gcd not determined, set to 1: " + G); // + ", A = " + A); 145 return r.getONE(); 146 } 147 148 149 /** 150 * Right greatest common divisor via least common multiple. 151 * @param r solvable polynomial ring. 152 * @param n first solvable polynomial. 153 * @param d second solvable polynomial. 154 * @return gcd(n,d) 155 */ 156 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> syzRightGcd( 157 GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 158 159 if (n.isZERO()) { 160 return d; 161 } 162 if (d.isZERO()) { 163 return n; 164 } 165 if (n.isConstant()) { 166 return r.getONE(); 167 } 168 if (d.isConstant()) { 169 return r.getONE(); 170 } 171 if (n.totalDegree() > 3 || d.totalDegree() > 3) { // how avoid too long running GBs ? 172 //if (n.totalDegree() + d.totalDegree() > 6) { // how avoid too long running GBs ? 173 // && n.length() < 10 && d.length() < 10 174 logger.warn("skipping GB computation: degs = " + n.totalDegree() + ", " + d.totalDegree()); 175 return r.getONE(); 176 } 177 List<GenSolvablePolynomial<C>> A = new ArrayList<GenSolvablePolynomial<C>>(2); 178 A.add(n); 179 A.add(d); 180 SolvableGroebnerBaseAbstract<C> sbb = new SolvableGroebnerBaseSeq<C>(); 181 logger.warn("right syzGcd computing GB: " + A); 182 List<GenSolvablePolynomial<C>> G = sbb.leftGB(A); // not: sbb.twosidedGB(A); 183 if (debug) { 184 logger.info("G = " + G); 185 } 186 if (G.size() == 1) { 187 return G.get(0); 188 } 189 logger.warn("gcd not determined, set to 1: " + G); // + ", A = " + A); 190 return r.getONE(); 191 } 192 193 194 /** 195 * Greatest common divisor and cofactors via least common multiple and 196 * reduction. 197 * @param r solvable polynomial ring. 198 * @param n first solvable polynomial. 199 * @param d second solvable polynomial. 200 * @return [ g=gcd(n,d), n/g, d/g ] 201 */ 202 @SuppressWarnings({ "unchecked", "cast" }) 203 public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C>[] syzGcdCofactors( 204 GenSolvablePolynomialRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 205 GenSolvablePolynomial<C>[] res = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[3]; 206 res[0] = PolyModUtil.<C> syzGcd(r, n, d); 207 res[1] = n; 208 res[2] = d; 209 if (res[0].isONE()) { 210 return res; 211 } 212 GenSolvablePolynomial<C>[] nqr = PolyGBUtil.<C> quotientRemainder(n, res[0]); 213 if (!nqr[1].isZERO()) { 214 res[0] = r.getONE(); 215 return res; 216 } 217 GenSolvablePolynomial<C>[] dqr = PolyGBUtil.<C> quotientRemainder(d, res[0]); 218 if (!dqr[1].isZERO()) { 219 res[0] = r.getONE(); 220 return res; 221 } 222 res[1] = nqr[0]; 223 res[2] = dqr[0]; 224 return res; 225 } 226 227 228 /** 229 * Least common multiple. Just for fun, is not efficient. 230 * @param r polynomial ring. 231 * @param n first polynomial. 232 * @param d second polynomial. 233 * @return lcm(n,d) 234 */ 235 public static <C extends GcdRingElem<C>> GenPolynomial<C> syzLcm(GenPolynomialRing<C> r, 236 GenPolynomial<C> n, GenPolynomial<C> d) { 237 List<GenPolynomial<C>> A = new ArrayList<GenPolynomial<C>>(1); 238 A.add(n); 239 List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(1); 240 B.add(d); 241 List<GenPolynomial<C>> c = PolyGBUtil.<C> intersect(r, A, B); 242 if (c.size() != 1) { 243 logger.warn("lcm not uniqe: " + c); 244 //throw new RuntimeException("lcm not uniqe: " + c); 245 } 246 GenPolynomial<C> lcm = c.get(0); 247 return lcm; 248 } 249 250 251 /** 252 * Greatest common divisor. Just for fun, is not efficient. 253 * @param r polynomial ring. 254 * @param n first polynomial. 255 * @param d second polynomial. 256 * @return gcd(n,d) 257 */ 258 public static <C extends GcdRingElem<C>> GenPolynomial<C> syzGcd(GenPolynomialRing<C> r, 259 GenPolynomial<C> n, GenPolynomial<C> d) { 260 if (n.isZERO()) { 261 return d; 262 } 263 if (d.isZERO()) { 264 return n; 265 } 266 if (n.isONE()) { 267 return n; 268 } 269 if (d.isONE()) { 270 return d; 271 } 272 GenPolynomial<C> p = n.multiply(d); 273 GenPolynomial<C> lcm = syzLcm(r, n, d); 274 GenPolynomial<C> gcd = PolyUtil.<C> basePseudoDivide(p, lcm); 275 return gcd; 276 } 277 278 279}