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