001    /*
002     * $Id: FactorAlgebraicPrim.java 3753 2011-08-27 20:34:30Z kredel $
003     */
004    
005    package edu.jas.application;
006    
007    
008    import java.util.ArrayList;
009    import java.util.List;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.poly.AlgebraicNumber;
014    import edu.jas.poly.AlgebraicNumberRing;
015    import edu.jas.poly.GenPolynomial;
016    import edu.jas.poly.GenPolynomialRing;
017    import edu.jas.poly.PolyUtil;
018    import edu.jas.poly.TermOrder;
019    import edu.jas.structure.GcdRingElem;
020    import edu.jas.ufd.FactorAbstract;
021    import edu.jas.ufd.FactorAbsolute;
022    //import edu.jas.ufd.FactorFactory;
023    import edu.jas.ufd.Squarefree;
024    import edu.jas.ufd.SquarefreeFactory;
025    import edu.jas.ufd.PolyUfdUtil;
026    
027    
028    /**
029     * Algebraic number coefficients factorization algorithms. This class implements
030     * factorization methods for polynomials over algebraic numbers over rational
031     * numbers or over (prime) modular integers.
032     * @author Heinz Kredel
033     * @param <C> coefficient type
034     */
035    
036    public class FactorAlgebraicPrim<C extends GcdRingElem<C>> extends FactorAbsolute<AlgebraicNumber<C>> {
037    
038    
039        //FactorAbstract<AlgebraicNumber<C>>
040    
041    
042        private static final Logger logger = Logger.getLogger(FactorAlgebraicPrim.class);
043    
044    
045        private final boolean debug = true || logger.isInfoEnabled();
046    
047    
048        /**
049         * Factorization engine for base coefficients.
050         */
051        public final FactorAbstract<C> factorCoeff;
052    
053    
054        /**
055         * No argument constructor. <b>Note:</b> can't use this constructor.
056         */
057        protected FactorAlgebraicPrim() {
058            throw new IllegalArgumentException("don't use this constructor");
059        }
060    
061    
062        /**
063         * Constructor.
064         * @param fac algebraic number factory.
065         */
066        public FactorAlgebraicPrim(AlgebraicNumberRing<C> fac) {
067            super(fac);
068            this.factorCoeff = FactorFactory.<C> getImplementation(fac.ring.coFac);
069        }
070    
071    
072        /**
073         * GenPolynomial base factorization of a squarefree polynomial.
074         * @param P squarefree GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
075         * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
076         */
077        @Override
078        public List<GenPolynomial<AlgebraicNumber<C>>> baseFactorsSquarefree(GenPolynomial<AlgebraicNumber<C>> P) {
079            if (P == null) {
080                throw new IllegalArgumentException(this.getClass().getName() + " P == null");
081            }
082            List<GenPolynomial<AlgebraicNumber<C>>> factors = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>();
083            if (P.isZERO()) {
084                return factors;
085            }
086            if (P.isONE()) {
087                factors.add(P);
088                return factors;
089            }
090            GenPolynomialRing<AlgebraicNumber<C>> pfac = P.ring; // Q(alpha)[x]
091            if (pfac.nvar > 1) {
092                throw new IllegalArgumentException("only for univariate polynomials");
093            }
094            AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac;
095    
096            AlgebraicNumber<C> ldcf = P.leadingBaseCoefficient();
097            if (!ldcf.isONE()) {
098                P = P.monic();
099                factors.add(pfac.getONE().multiply(ldcf));
100            }
101            //System.out.println("\nP = " + P);
102            if (false && debug) {
103               Squarefree<AlgebraicNumber<C>> sqengine = SquarefreeFactory.<AlgebraicNumber<C>> getImplementation(afac);
104               if ( !sqengine.isSquarefree(P) ) {
105                   throw new RuntimeException("P not squarefree: " + sqengine.squarefreeFactors(P));
106               }
107               GenPolynomial<C> modu = afac.modul;
108               if ( !factorCoeff.isIrreducible(modu) ) {
109                   throw new RuntimeException("modul not irreducible: " + factorCoeff.factors(modu));
110               }
111               System.out.println("P squarefree and modul irreducible via ideal decomposition");
112               //GreatestCommonDivisor<AlgebraicNumber<C>> aengine //= GCDFactory.<AlgebraicNumber<C>> getProxy(afac);
113               //  = new GreatestCommonDivisorSimple<AlgebraicNumber<C>>( /*cfac.coFac*/ );
114            }
115            GenPolynomial<C> agen = afac.modul;
116            GenPolynomialRing<C> cfac = afac.ring;
117            GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pfac);
118            // transform minimal polynomial to bi-variate polynomial
119            GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, agen);
120            //System.out.println("Ac = " + Ac.toScript());
121            // transform to bi-variate polynomial, 
122            // switching varaible sequence from Q[alpha][x] to Q[X][alpha]
123            GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> substituteFromAlgebraicCoefficients(rfac, P, 0);
124            Pc = PolyUtil.<C> monic(Pc);
125            //System.out.println("Pc = " + Pc.toScript());
126            // distribute 
127            TermOrder to = new TermOrder(TermOrder.INVLEX);
128            String[] vars = new String[2];
129            vars[0] = cfac.getVars()[0];
130            vars[1] = rfac.getVars()[0];
131            GenPolynomialRing<C> dfac = new GenPolynomialRing<C>(cfac.coFac, to, vars);
132            GenPolynomial<C> Ad = agen.extend(dfac,0,0L); 
133            Pc = PolyUtil.<C> fromAlgebraicCoefficients(rfac,P);
134            GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac,Pc);
135            //System.out.println("Ad = " + Ad.toScript());
136            //System.out.println("Pd = " + Pd.toScript());
137    
138            List<GenPolynomial<C>> id = new ArrayList<GenPolynomial<C>>(2);
139            id.add(Ad);
140            id.add(Pd);
141            Ideal<C> I = new Ideal<C>(dfac,id);
142            List<IdealWithUniv<C>> Iul = I.zeroDimPrimeDecomposition(); 
143            //System.out.println("prime decomp = " + Iul);
144            if ( Iul.size() == 1 ) {
145                factors.add(P);
146                return factors;
147            }
148            GenPolynomial<AlgebraicNumber<C>> f = pfac.getONE();
149            for (IdealWithUniv<C> Iu : Iul ) {
150                GenPolynomial<C> ag = PolyUtil.<C> selectWithVariable(Iu.ideal.getList(),1); 
151                GenPolynomial<C> pg = PolyUtil.<C> selectWithVariable(Iu.ideal.getList(),0); 
152                //System.out.println("ag = " + ag.toScript());
153                //System.out.println("pg = " + pg.toScript());
154                if ( ag.equals(Ad) ) {
155                    //System.out.println("found factor --------------------");
156                    GenPolynomial<GenPolynomial<C>> pgr = PolyUtil.<C> recursive(rfac,pg); 
157                    GenPolynomial<AlgebraicNumber<C>> pga = PolyUtil.<C> convertRecursiveToAlgebraicCoefficients(pfac, pgr); 
158                    //System.out.println("pga = " + pga.toScript());
159                    f = f.multiply(pga);
160                    factors.add(pga);
161                }
162            }
163            f = f.subtract(P);
164            //System.out.println("f = " + f.toScript());
165            if ( !f.isZERO() ) {
166                throw new RuntimeException("no factorization: " + f + ", factors = " + factors);
167            }
168            return factors;
169            //return new edu.jas.ufd.FactorAlgebraic<C>(afac).baseFactorsSquarefree(P);
170        }
171    
172    }