source: git/kernel/fast_maps.cc @ 208e0c

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