source: git/kernel/fast_maps.cc @ 40f802d

spielwiese
Last change on this file since 40f802d was 40f802d, checked in by Hans Schönemann <hannes@…>, 14 years ago
libsingular: fast_map and zero-div. git-svn-id: file:///usr/local/Singular/svn/trunk@12514 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.2 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    fast_maps.cc
6 *  Purpose: implementation of fast maps
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 02/01
9 *  Version: $Id$
10 *******************************************************************/
11#include "mod2.h"
12#include <omalloc.h>
13#include "options.h"
14#include "p_polys.h"
15#include "prCopy.h"
16#include "ideals.h"
17#include "ring.h"
18#include "febase.h"
19#include "fast_maps.h"
20
21// define if you want to use special dest_ring
22#define HAVE_DEST_R 1
23// define if you want to use special src_ring
24#define HAVE_SRC_R 1
25// define if you want to use optimization step
26#define HAVE_MAP_OPTIMIZE 1
27
28/*******************************************************************************
29**
30*F  maMaxExp  . . . . . . . .  returns bound on maximal exponent of result of map
31*/
32// return maximal monomial if max_map_monomials are substituted into pi_m
33static poly maGetMaxExpP(poly* max_map_monomials,
34                         int n_max_map_monomials, ring map_r,
35                         poly pi_m, ring pi_r)
36{
37  int n = si_min(pi_r->N, n_max_map_monomials);
38  int i, j;
39  unsigned long e_i, e_j;
40  poly m_i=NULL;
41  poly map_j = p_Init(map_r);
42
43  for (i=1; i <= n; i++)
44  {
45    e_i = p_GetExp(pi_m, i, pi_r);
46    if (e_i==0) e_i=1;
47    m_i = max_map_monomials[i-1];
48    if (m_i != NULL && ! p_IsConstantComp(m_i, map_r))
49    {
50      for (j = 1; j<= map_r->N; j++)
51      {
52        e_j = p_GetExp(m_i, j, map_r);
53        if (e_j == 0) e_j=1;
54        p_AddExp(map_j, j, e_j*e_i, map_r);
55      }
56    }
57  }
58  return map_j;
59}
60
61// returns maximal exponent if map_id is applied to pi_id
62static unsigned long maGetMaxExp(ideal pi_id, ring pi_r, ideal map_id, ring map_r)
63{
64  unsigned long max=0;
65  poly* max_map_monomials = (poly*) omAlloc(IDELEMS(map_id)*sizeof(poly));
66  poly max_pi_i, max_map_i;
67
68  int i, j;
69  for (i=0; i<IDELEMS(map_id); i++)
70  {
71    max_map_monomials[i] = p_GetMaxExpP(map_id->m[i], map_r);
72  }
73
74  for (i=0; i<IDELEMS(pi_id); i++)
75  {
76    max_pi_i = p_GetMaxExpP(pi_id->m[i], pi_r);
77    max_map_i = maGetMaxExpP(max_map_monomials, IDELEMS(map_id), map_r,
78                              max_pi_i, pi_r);
79    unsigned long temp = p_GetMaxExp(max_map_i, map_r);
80    if (temp > max){ max=temp; }
81
82    p_LmFree(max_pi_i, pi_r);
83    p_LmFree(max_map_i, map_r);
84  }
85  for (i=0; i<IDELEMS(map_id); i++)
86  {
87    p_Delete(&max_map_monomials[i], map_r);
88  }
89  omFreeSize(max_map_monomials,IDELEMS(map_id)*sizeof(poly));
90
91  return max;
92}
93
94
95/*******************************************************************************
96**
97*F  debugging stuff
98*/
99#ifndef NDEBUG
100void maMonomial_Out(mapoly monomial, ring src_r, ring dest_r)
101{
102  p_wrp(monomial->src, src_r);
103  printf(" ref:%d", monomial->ref);
104  if (dest_r != NULL)
105  {
106    printf(" dest:");
107    p_wrp(monomial->dest, dest_r);
108  }
109  if (monomial->f1!=NULL) { printf(" f1:%lx", (long)monomial->f1->src);
110                            // p_wrp(monomial->f1->src, src_r);
111                          }
112  if (monomial->f2!=NULL) { printf(" f2:%lx",(long)monomial->f2->src);
113                            // p_wrp(monomial->f2->src, src_r);
114                          }
115  printf("\n");
116  fflush(stdout);
117}
118
119void maPoly_Out(mapoly mpoly, ring src_r, ring dest_r)
120{
121  while (mpoly != NULL)
122  {
123    maMonomial_Out(mpoly, src_r, dest_r);
124    mpoly = mpoly->next;
125  }
126}
127#endif
128
129/*******************************************************************************
130**
131*F  mapolyCreate  . . . . . . . . . . . . . . .  Creates mapoly
132*/
133static omBin mapolyBin = omGetSpecBin(sizeof(mapoly_s));
134static omBin macoeffBin = omGetSpecBin(sizeof(macoeff_s));
135
136mapoly maMonomial_Create(poly p, ring r_p, sBucket_pt bucket)
137{
138  mapoly mp = (mapoly) omAlloc0Bin(mapolyBin);
139  //p_wrp(p,r_p);printf(" (%x) created\n",mp);
140  mp->src = p;
141  p->next = NULL;
142
143  if (bucket != NULL)
144  {
145    mp->coeff = (macoeff) omAlloc0Bin(macoeffBin);
146    mp->coeff->bucket = bucket;
147    mp->coeff->n = pGetCoeff(p);
148  }
149  mp->ref = 1;
150  return mp;
151}
152
153void maMonomial_Destroy(mapoly mp, ring src_r, ring dest_r)
154{
155  if (mp != NULL)
156  {
157    p_LmFree(mp->src, src_r);
158    if (mp->coeff != NULL)
159    {
160      macoeff coeff, next = mp->coeff;
161      do
162      {
163        coeff = next;
164        next = coeff->next;
165        omFreeBin(coeff, macoeffBin);
166      }
167      while (next != NULL);
168      if (mp->dest != NULL)
169      {
170        assume(dest_r != NULL);
171        p_Delete(&(mp->dest), dest_r);
172      }
173    }
174  }
175  omFreeBin(mp, mapolyBin);
176}
177
178/*******************************************************************************
179**
180*F  maPoly_InsertMonomial . . . . . . . . .insertion of a monomial into mapoly
181*/
182mapoly maPoly_InsertMonomial(mapoly &into, mapoly what, ring src_r)
183{
184  if (into == NULL)
185  {
186    into = what;
187    return what;
188  }
189
190  mapoly iter = into;
191  mapoly prev = NULL;
192
193  Top:
194  p_LmCmpAction(iter->src, what->src, src_r, goto Equal, goto Greater, goto Smaller);
195
196  Greater:
197  if (iter->next == NULL)
198  {
199    iter->next = what;
200    return what;
201  }
202  prev = iter;
203  iter = iter->next;
204  goto Top;
205
206  Smaller:
207  if (prev == NULL)
208  {
209    into = what;
210    what->next = iter;
211    return what;
212  }
213  prev->next = what;
214  what->next = iter;
215  return what;
216
217  Equal:
218  iter->ref += what->ref;
219  macoeff coeff = what->coeff;
220  if (coeff != NULL)
221  {
222    while (coeff->next != NULL) coeff = coeff->next;
223    coeff->next = iter->coeff;
224    iter->coeff = what->coeff;
225    what->coeff = NULL;
226  }
227  maMonomial_Free(what, src_r);
228  return iter;
229}
230
231mapoly maPoly_InsertMonomial(mapoly &into, poly p, ring src_r, sBucket_pt bucket)
232{
233  return maPoly_InsertMonomial(into, maMonomial_Create(p, src_r, bucket), src_r);
234}
235
236static void maPoly_InsertPoly(mapoly &into, poly what, ring src_r, sBucket_pt bucket)
237{
238  poly next;
239
240  while (what != NULL)
241  {
242    next = what->next;
243    maPoly_InsertMonomial(into, what, src_r, bucket);
244    what = next;
245  }
246}
247
248/*******************************************************************************
249**
250*F  maMap_Create . . . . . . . . . . . . . . . . . . . . create stuff
251*/
252
253void maMap_CreatePolyIdeal(ideal map_id, ring map_r, ring src_r, ring dest_r,
254                           mapoly &mp, maideal &mideal)
255{
256  mideal = (maideal) omAlloc0(sizeof(maideal_s));
257  mideal->n = IDELEMS(map_id);
258  mideal->buckets = (sBucket_pt*) omAlloc0(mideal->n*sizeof(sBucket_pt));
259  int i;
260  mp = NULL;
261
262  for (i=0; i<mideal->n; i++)
263  {
264    if (map_id->m[i] != NULL)
265    {
266      mideal->buckets[i] = sBucketCreate(dest_r);
267      maPoly_InsertPoly(mp,
268#ifdef PDEBUG
269                        prShallowCopyR(map_id->m[i], map_r, src_r),
270#else
271                        prShallowCopyR_NoSort(map_id->m[i], map_r, src_r),
272#endif
273                        src_r,
274                        mideal->buckets[i]);
275    }
276  }
277}
278
279void maMap_CreateRings(ideal map_id, ring map_r,
280                       ideal image_id, ring image_r,
281                       ring &src_r, ring &dest_r, BOOLEAN &simple)
282{
283#if HAVE_SRC_R > 0
284  int* weights = (int*) omAlloc0(map_r->N*sizeof(int));
285  int i;
286  int n = si_min(map_r->N, IDELEMS(image_id));
287
288  for (i=0; i<n; i++)
289  {
290    weights[i] = pLength(image_id->m[i])+1;
291  }
292  src_r = rModifyRing_Wp(map_r, weights);
293#else
294  src_r = map_r;
295#endif
296
297#if HAVE_DEST_R > 0
298  unsigned long maxExp = maGetMaxExp(map_id, map_r, image_id, image_r);
299  if (maxExp <=  1) maxExp = 2;
300  else if (maxExp > (unsigned long) image_r->bitmask)
301    maxExp = (unsigned long) image_r->bitmask;
302  dest_r = rModifyRing_Simple(image_r, TRUE, TRUE, maxExp,  simple);
303#else
304  dest_r = image_r;
305#endif
306}
307
308static void maMap_KillRings(ring map_r, ring image_r, ring src_r, ring dest_r)
309{
310  if (map_r != src_r)
311    rKillModified_Wp_Ring(src_r);
312  if (image_r != dest_r)
313    rKillModifiedRing_Simple(dest_r);
314}
315
316/*******************************************************************************
317**
318*F  misc  . . . . . . . . . . . . . . . . . . . . . . . . . . . .  misc  stuff
319*/
320
321ideal maIdeal_2_Ideal(maideal m_id, ring dest_r)
322{
323  ideal res = idInit(m_id->n, 1);
324  int l;
325
326  for (int i= 0; i < m_id->n; i++)
327  {
328    if (m_id->buckets[i]!=NULL)
329      sBucketDestroyAdd(m_id->buckets[i], &(res->m[i]), &l);
330  }
331  omFreeSize(m_id->buckets,m_id->n*sizeof(sBucket_pt));
332  omFree(m_id);
333  return res;
334}
335
336void maPoly_GetLength(mapoly mp, int &length)
337{
338  length = 0;
339  while (mp != NULL)
340  {
341    length++;
342    mp = mp->next;
343  }
344}
345
346
347/*******************************************************************************
348**
349*F  fast_map  . . . . . . . . . . . . . . . . . . . . . . . . . .the real thing
350*/
351
352ideal fast_map(ideal map_id, ring map_r, ideal image_id, ring image_r)
353{
354  ring src_r, dest_r;
355  ideal dest_id, res_id;
356  int length = 0;
357  BOOLEAN no_sort;
358
359  // construct rings we work in:
360  // src_r: Wp with Weights set to length of poly in image_id
361  // dest_r: Simple ring without degree ordering and short exponents
362  maMap_CreateRings(map_id, map_r, image_id, image_r, src_r, dest_r, no_sort);
363
364  // construct dest_id
365  if (dest_r != image_r)
366  {
367    dest_id = idrShallowCopyR(image_id, image_r, dest_r);
368  }
369  else
370    dest_id = image_id;
371
372  // construct mpoly and mideal
373  mapoly mp;
374  maideal mideal;
375  maMap_CreatePolyIdeal(map_id, map_r, src_r, dest_r, mp, mideal);
376
377  if (TEST_OPT_PROT)
378  {
379    maPoly_GetLength(mp, length);
380    Print("map[%ld:%d]{%d:", dest_r->bitmask, dest_r->ExpL_Size, length);
381  }
382
383  // do the optimization step
384#if HAVE_MAP_OPTIMIZE > 0
385  if (mp!=NULL) maPoly_Optimize(mp, src_r);
386#endif
387  if (TEST_OPT_PROT)
388  {
389    maPoly_GetLength(mp, length);
390    Print("%d}", length);
391  }
392
393  // do the actual evaluation
394  maPoly_Eval(mp, src_r, dest_id, dest_r, length);
395  if (TEST_OPT_PROT) Print(".");
396
397  // collect the results back into an ideal
398  ideal res_dest_id = maIdeal_2_Ideal(mideal, dest_r);
399  if (TEST_OPT_PROT) Print(".");
400
401  // convert result back to image_r
402  ideal res_image_id;
403  if (dest_r != image_r)
404  {
405    //if (no_sort) see Old/m134si.tst
406    //  res_image_id = idrShallowCopyR_NoSort(res_dest_id, dest_r, image_r);
407    //else
408      res_image_id = idrShallowCopyR(res_dest_id, dest_r, image_r);
409    id_ShallowDelete(&res_dest_id, dest_r);
410    id_ShallowDelete(&dest_id,dest_r);
411  }
412  else
413    res_image_id = res_dest_id;
414
415  if (TEST_OPT_PROT) Print(".");
416
417  // clean-up the rings
418  maMap_KillRings(map_r, image_r, src_r, dest_r);
419
420  if (TEST_OPT_PROT)
421    Print("\n");
422
423  idTest(res_image_id);
424  return res_image_id;
425}
426
427
428/**********************************************************************
429* Evaluation stuff                                                    *
430**********************************************************************/
431
432// substitute p everywhere the monomial occours,
433// return the number of substitutions
434static int maPoly_Substitute(macoeff c, poly p, ring dest_r)
435{
436  // substitute the monomial: go through macoeff
437  int len=pLength(p);
438  int done=0;
439  while (c!=NULL)
440  {
441    done++;
442    poly t=pp_Mult_nn(p,c->n,dest_r);
443    sBucket_Add_p(c->bucket, t, len);
444    c=c->next;
445  }
446  return done;
447}
448
449static poly maPoly_EvalMon(poly src, ring src_r, poly* dest_id, ring dest_r)
450{
451  int i;
452  int e;
453  poly p=NULL;
454  poly pp;
455  BOOLEAN is_const=TRUE; // to check for zero-div in p_Mult_q
456  for(i=1;i<=src_r->N;i++)
457  {
458    e=p_GetExp(src,i,src_r);
459    if (e>0)
460    {
461      is_const=FALSE;
462      pp=dest_id[i-1];
463      if (pp==NULL)
464      {
465        p_Delete(&p,dest_r);
466        return NULL;
467      }
468      if ((p==NULL) /* && (e>0)*/)
469      {
470        p=p_Copy(pp /*dest_id[i-1]*/,dest_r);
471        e--;
472      }
473      while (e>0)
474      {
475        p=p_Mult_q(p,p_Copy(pp /*dest_id[i-1]*/,dest_r),dest_r);
476        e--;
477      }
478    }
479  }
480  if (is_const)
481  { 
482    assume(p==NULL);
483    p=p_ISet(1,dest_r);
484  }
485  return p;
486}
487
488void maPoly_Eval(mapoly root, ring src_r, ideal dest_id, ring dest_r, int total_cost)
489{
490  // invert the list rooted at root:
491  if ((root!=NULL) && (root->next!=NULL))
492  {
493    mapoly q=root->next;
494    mapoly qn;
495    root->next=NULL;
496    do
497    {
498      qn=q->next;
499      q->next=root;
500      root=q;
501      q=qn;
502    }
503    while (qn !=NULL);
504  }
505
506  total_cost /= 10;
507  int next_print_cost = total_cost;
508
509  // the evaluation -----------------------------------------
510  mapoly p=root;
511  int cost = 0;
512
513  while (p!=NULL)
514  {
515    // look at each mapoly: compute its value in ->dest
516    assume (p->dest==NULL);
517    {
518      if ((p->f1!=NULL)&&(p->f2!=NULL))
519      {
520        poly f1=p->f1->dest;
521        poly f2=p->f2->dest;
522        if (p->f1->ref>0) f1=p_Copy(f1,dest_r);
523        else
524        {
525          // we own p->f1->dest now (in f1)
526          p->f1->dest=NULL;
527        }
528        if (p->f2->ref>0) f2=p_Copy(f2,dest_r);
529        else
530        {
531          // we own p->f2->dest now (in f2)
532          p->f2->dest=NULL;
533        }
534        maMonomial_Free(p->f1,src_r, dest_r);
535        maMonomial_Free(p->f2,src_r, dest_r);
536        p->dest=p_Mult_q(f1,f2,dest_r);
537      } /* factors : 2 */
538      else
539      {
540        assume((p->f1==NULL) && (p->f2==NULL));
541        // no factorization provided, use the classical method:
542        p->dest=maPoly_EvalMon(p->src,src_r,dest_id->m,dest_r);
543      }
544    } /* p->dest==NULL */
545    // substitute the monomial: go through macoeff
546    p->ref -= maPoly_Substitute(p->coeff, p->dest, dest_r);
547    //printf("subst done\n");
548    if (total_cost)
549    {
550      assume(TEST_OPT_PROT);
551      cost++;
552      if (cost > next_print_cost)
553      {
554        Print("-");
555        next_print_cost += total_cost;
556      }
557    }
558
559    mapoly pp=p;
560    p=p->next;
561    //p_wrp(pp->src, src_r);
562    if (pp->ref<=0)
563    {
564      //printf(" (%x) killed\n",pp);
565      maMonomial_Destroy(pp, src_r, dest_r);
566    }
567    //else
568    //  printf(" (%x) not killed, ref=%d\n",pp,pp->ref);
569  }
570}
571
572
573/*******************************************************************************
574**
575*F  maEggt  . . . . . . . . . . . . . . . . . . . . . . . .  returns extended ggt
576*/
577// return NULL if deg(ggt(m1, m2)) < 2
578// else return m = ggT(m1, m2) and q1, q2 such that m1 = q1*m m2 = q2*m
579static poly maEggT(const poly m1, const poly m2, poly &q1, poly &q2,const ring r)
580{
581
582  int i;
583  int dg = 0;
584  poly ggt = p_Init(r);
585  q1 = p_Init(r);
586  q2 = p_Init(r);
587
588  for (i=1;i<=r->N;i++)
589  {
590    unsigned long e1 = p_GetExp(m1, i, r);
591    unsigned long e2 = p_GetExp(m2, i, r);
592    if (e1 > 0 && e2 > 0)
593    {
594      unsigned long em = (e1 > e2 ? e2 : e1);
595      dg += em;
596      p_SetExp(ggt, i, em, r);
597      p_SetExp(q1, i, e1 - em, r);
598      p_SetExp(q2, i, e2 - em, r);
599    }
600    else
601    {
602      p_SetExp(q1, i, e1, r);
603      p_SetExp(q2, i, e2, r);
604    }
605  }
606  if (dg>1)
607  {
608    p_Setm(ggt, r);
609    p_Setm(q1, r);
610    p_Setm(q2, r);
611  }
612  else
613  {
614    p_LmFree(ggt, r);
615    p_LmFree(q1, r);
616    p_LmFree(q2, r);
617    ggt = NULL;
618  }
619  return ggt;
620}
621
622/********************************************************************
623 **                                                                 *
624 * maFindBestggT                                                    *
625 * finds ggT with the highest cost                                  *
626 *******************************************************************/
627
628static mapoly maFindBestggT(mapoly mp, mapoly & choice, mapoly & fp, mapoly & fq,const ring r)
629{
630  int ggt_deg = 0;
631  poly p = mp->src;
632  mapoly iter = choice;
633  poly ggT = NULL;
634  fp = NULL;
635  fq = NULL;
636  poly fp_p=NULL;
637  poly fq_p=NULL;
638  choice=NULL;
639  while ((iter != NULL) && (pDeg(iter->src, r) > ggt_deg))
640  {
641    //    maMonomial_Out(iter, r, NULL);
642    poly q1, q2, q;
643
644    q = maEggT(p, iter->src, q1, q2,r);
645    if (q != NULL)
646    {
647      int tmp_deg;
648      assume((q1!=NULL)&&(q2!=NULL));
649      if ((tmp_deg=pDeg(q,r)) > ggt_deg)
650      {
651        choice=iter;
652        if (ggT != NULL)
653        {
654          p_LmFree(ggT, r);
655          p_LmFree(fp_p, r);
656          p_LmFree(fq_p, r);
657        }
658        ggt_deg = tmp_deg ; /*pDeg(q, r);*/
659        ggT = q;
660        fp_p = q1;
661        fq_p = q2;
662      }
663      else
664      {
665        p_LmFree(q, r);
666        p_LmFree(q1, r);
667        p_LmFree(q2, r);
668      }
669    }
670    iter=iter->next;
671  }
672  if(ggT!=NULL)
673  {
674    int dq =pTotaldegree(fq_p,r);
675    if (dq!=0)
676    {
677      fq=maPoly_InsertMonomial(mp, fq_p, r, NULL);
678      fp=maPoly_InsertMonomial(mp, fp_p, r, NULL);
679      return maPoly_InsertMonomial(mp, ggT, r, NULL);
680    }
681    else
682    {
683      fq=NULL;
684      p_LmFree(fq_p, r);
685      p_LmFree(ggT, r);
686      fp=maPoly_InsertMonomial(mp, fp_p, r, NULL);
687      choice->ref++;
688      return choice;
689    }
690  }
691  else
692  {
693    return NULL;
694  }
695}
696
697/********************************************************************
698 **                                                                 *
699 * maPoly_Optimize                                                  *
700 * adds and integrates subexpressions                               *
701 *******************************************************************/
702
703void maPoly_Optimize(mapoly mpoly, ring src_r)
704{
705  assume(mpoly!=NULL && mpoly->src!=NULL);
706  mapoly iter = mpoly;
707  mapoly choice;
708  mapoly ggT=NULL;
709  mapoly fp=NULL;
710  mapoly fq=NULL;
711  while (iter->next!=NULL)
712  {
713    choice=iter->next;
714    if ((iter->f1==NULL))
715    {
716      ggT=maFindBestggT(iter, choice, fp, fq,src_r);
717      if (choice!=NULL)
718      {
719        assume(iter->f1==NULL);
720        assume(iter->f2==NULL);
721        iter->f1=fp;
722        iter->f2=ggT;
723        if (fq!=NULL)
724        {
725          ggT->ref++;
726          choice->f1=fq;
727          choice->f2=ggT;
728        }
729      }
730      else assume(ggT==NULL);
731    }
732    iter=iter->next;
733  }
734}
Note: See TracBrowser for help on using the repository browser.