source: git/Singular/dyn_modules/syzextra/syzextra.h @ 2ded87

fieker-DuValspielwiese
Last change on this file since 2ded87 was 2ded87, checked in by Oleksandr Motsak <motsak@…>, 9 years ago
Added statistic counting to Syzygy computation inside syzextra added: a macro RTIMER_BENCHMARKING which if option(prot) will cause the output of timestamps around the most important calls
  • Property mode set to 100644
File size: 14.6 KB
Line 
1// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2/*****************************************************************************\
3 * Computer Algebra System SINGULAR
4\*****************************************************************************/
5/** @file syzextra.h
6 *
7 * Computation of Syzygies
8 *
9 * ABSTRACT: Computation of Syzygies due to Schreyer
10 *
11 * @author Oleksandr Motsak
12 *
13 **/
14/*****************************************************************************/
15
16#ifndef SYZEXTRA_H
17#define SYZEXTRA_H
18
19#include <vector>
20#include <map>
21#include <string.h>
22
23// include basic definitions
24#include "singularxx_defs.h"
25
26struct spolyrec; typedef struct spolyrec polyrec; typedef polyrec* poly;
27struct ip_sring; typedef struct ip_sring* ring; typedef struct ip_sring const* const_ring;
28
29struct sip_sideal; typedef struct sip_sideal *       ideal;
30class idrec; typedef idrec *   idhdl;
31
32class sBucket; typedef sBucket* sBucket_pt;
33class kBucket; typedef kBucket* kBucket_pt;
34
35
36BEGIN_NAMESPACE_SINGULARXX    BEGIN_NAMESPACE(SYZEXTRA)
37
38poly leadmonom(const poly p, const ring r, const bool bSetZeroComp = true);
39
40/// return the tail of a given polynomial or vector
41/// returns NULL if input is NULL, otherwise
42/// the result is a new polynomial/vector in the ring r
43poly p_Tail(const poly p, const ring r);
44
45
46/// return the tail of a given ideal or module
47/// returns NULL if input is NULL, otherwise
48/// the result is a new ideal/module in the ring r
49/// NOTE: the resulting rank is autocorrected
50ideal id_Tail(const ideal id, const ring r);
51
52/// inplace sorting of the module (ideal) id wrt <_(c,ds)
53void Sort_c_ds(const ideal id, const ring r);
54
55
56
57
58
59/// Computation attribute storage
60struct SchreyerSyzygyComputationFlags
61{
62    SchreyerSyzygyComputationFlags(idhdl rootRingHdl);
63
64    SchreyerSyzygyComputationFlags(const SchreyerSyzygyComputationFlags& attr):
65        __DEBUG__(attr.__DEBUG__),
66        __LEAD2SYZ__(attr.__LEAD2SYZ__),  __TAILREDSYZ__(attr.__TAILREDSYZ__),
67        __HYBRIDNF__(attr.__HYBRIDNF__), __IGNORETAILS__(attr.__IGNORETAILS__),
68        __SYZNUMBER__(attr.__SYZNUMBER__), __TREEOUTPUT__(attr.__TREEOUTPUT__),
69        __SYZCHECK__(attr.__SYZCHECK__), __PROT__(attr.__PROT__),
70        m_rBaseRing(attr.m_rBaseRing)
71    {}
72
73  /// output all the intermediate states
74  const int __DEBUG__; // DebugOutput;
75
76  /// ?
77  const int __LEAD2SYZ__; // TwoLeadingSyzygyTerms;
78
79  /// Reduce syzygy tails wrt the leading syzygy terms
80  const int __TAILREDSYZ__; // TailReducedSyzygies;
81
82  /// Use the usual NF's S-poly reduction while dropping lower order terms
83  /// 2 means - smart selection!
84  const int __HYBRIDNF__; // UseHybridNF
85
86
87  /// ignore tails and compute the pure Schreyer frame
88  const int __IGNORETAILS__; // @IGNORETAILS
89
90  /// Syzygy level (within a resolution)
91  mutable int __SYZNUMBER__;
92
93  inline void  nextSyzygyLayer() const
94  {
95     __SYZNUMBER__++;
96  }
97
98  /// output lifting tree
99  const int __TREEOUTPUT__;
100
101  /// CheckSyzygyProperty: TODO
102  const int __SYZCHECK__;
103
104  /// TEST_OPT_PROT
105  const bool __PROT__;
106
107  /// global base ring
108  const ring m_rBaseRing;
109};
110
111class SchreyerSyzygyComputation;
112
113class CLCM: public SchreyerSyzygyComputationFlags, public std::vector<bool>
114{
115  public:
116    CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags);
117
118    bool Check(const poly m) const;
119
120  private:
121    bool m_compute;
122
123    const unsigned int m_N; ///< number of ring variables
124};
125
126
127class CLeadingTerm
128{
129  public:
130    CLeadingTerm(unsigned int label,  const poly lt, const ring);
131
132#ifndef SING_NDEBUG
133    ~CLeadingTerm();
134#endif
135   
136    bool DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const;
137    bool DivisibilityCheck(const poly multiplier, const poly t, const unsigned long not_sev, const ring r) const;
138
139    bool CheckLT( const ideal & L ) const;
140
141#ifndef SING_NDEBUG
142    poly lt() const;   
143    unsigned long sev() const;
144    unsigned int label() const;
145#else
146    inline poly lt() const { return m_lt; };
147    inline unsigned long sev() const { return m_sev; };
148    inline unsigned int label() const { return m_label; };   
149#endif
150   
151  private:
152    const unsigned long m_sev; ///< not short exp. vector
153   
154    // NOTE/TODO: either of the following should be enough:
155    const unsigned int  m_label; ///< index in the main L[] + 1
156
157    const poly          m_lt; ///< the leading term itself L[label-1]
158
159#ifndef SING_NDEBUG
160    const ring _R;  const poly          m_lt_copy; ///< original copy of LEAD(lt) (only for debug!!!)
161#endif 
162   
163    // disable the following:
164    CLeadingTerm();
165    CLeadingTerm(const CLeadingTerm&);
166    void operator=(const CLeadingTerm&);
167};
168
169
170// TODO: needs a specialized variant without a component (hash!)
171class CReducerFinder: public SchreyerSyzygyComputationFlags
172{
173  friend class CDivisorEnumerator;
174  friend class CDivisorEnumerator2;
175
176  public:
177    typedef long TComponentKey;
178    typedef std::vector<const CLeadingTerm*> TReducers;
179
180  private:
181    typedef std::map< TComponentKey, TReducers> CReducersHash;
182
183  public:
184    /// goes over all leading terms
185    CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags);
186
187    void Initialize(const ideal L);
188
189    ~CReducerFinder();
190
191    // TODO: save shortcut (syz: |-.->) LM(LM(m) * "t") -> syz?
192    poly // const_iterator // TODO: return const_iterator it, s.th: it->m_lt is the needed
193    FindReducer(const poly product, const poly syzterm, const CReducerFinder& checker) const;
194
195    bool IsDivisible(const poly q) const;
196
197    inline bool IsNonempty() const { return !m_hash.empty(); }
198
199    /// is the term to be "preprocessed" as lower order term or lead to only reducible syzygies...
200    int PreProcessTerm(const poly t, CReducerFinder& syzChecker) const;
201
202    poly FindReducer(const poly multiplier, const poly monom, const poly syzterm, const CReducerFinder& checker) const;
203
204#ifndef SING_NDEBUG
205    void DebugPrint() const;
206    void Verify() const;
207#endif
208
209  private:
210    ideal m_L; ///< only for debug
211
212    CReducersHash m_hash; // can also be replaced with a vector indexed by components
213
214  private:
215    CReducerFinder(const CReducerFinder&);
216    void operator=(const CReducerFinder&);
217};
218
219extern ideal id_Copy (const ideal, const ring);
220bool my_p_LmCmp (poly, poly, const ring);
221
222typedef poly TCacheKey;
223typedef poly TCacheValue;
224
225struct CCacheCompare
226{
227  const ring & m_ring;
228
229  CCacheCompare();
230
231  CCacheCompare(const ring& r): m_ring(r) { assume(r != NULL); }
232
233  CCacheCompare(const CCacheCompare& lhs): m_ring(lhs.m_ring) { assume(m_ring != NULL); }
234  CCacheCompare& operator=(const CCacheCompare& lhs) { assume(lhs.m_ring != NULL); return (const_cast<CCacheCompare&>(lhs)); }
235
236  inline bool operator() (const TCacheKey& l, const TCacheKey& r) const { assume(m_ring != NULL); return my_p_LmCmp(l, r, m_ring); }
237};
238
239typedef std::map<TCacheKey, TCacheValue, CCacheCompare> TP2PCache; // deallocation??? !!!
240typedef std::map<int, TP2PCache> TCache;
241
242/** @class SchreyerSyzygyComputation syzextra.h
243 *
244 * Computing syzygies after Schreyer
245 *
246 * Storing/accumulating data during the computation requires some global
247 * object, like this class. Ideally the above global functions should not
248 * be used in favour of this class.
249 *
250 * @sa Schreyer Syzygy Computation Paper & Talk & Python prototype
251 */
252class SchreyerSyzygyComputation: public SchreyerSyzygyComputationFlags
253{
254  friend class CLCM;
255  friend class CReducerFinder;
256
257  public:
258    /// Construct a global object for given input data (separated into leads & tails)
259    SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const SchreyerSyzygyComputationFlags setting):
260        SchreyerSyzygyComputationFlags(setting),
261        m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)),
262        m_syzLeads(NULL), m_syzTails(NULL),
263        m_LS(NULL), m_lcm(m_idLeads, setting),
264        m_div(m_idLeads, setting), m_checker(NULL, setting), m_cache(),
265        m_sum_bucket(NULL), m_spoly_bucket(NULL)
266    {
267      if( __PROT__ ) memset( &m_stat, 0, sizeof(m_stat) );
268    }
269
270    /// Construct a global object for given input data (separated into leads & tails)
271    SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const ideal syzLeads, const SchreyerSyzygyComputationFlags setting):
272        SchreyerSyzygyComputationFlags(setting),
273        m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)),
274        m_syzLeads(syzLeads), m_syzTails(NULL),
275        m_LS(syzLeads), m_lcm(m_idLeads, setting),
276        m_div(m_idLeads, setting), m_checker(NULL, setting), m_cache(),
277        m_sum_bucket(NULL), m_spoly_bucket(NULL)
278    {
279      if( __PROT__ ) memset( &m_stat, 0, sizeof(m_stat) );
280     
281      if( __TAILREDSYZ__ && !__IGNORETAILS__)
282      {
283        if (syzLeads != NULL)
284          m_checker.Initialize(syzLeads);
285//        if( idTails != NULL )
286//          SetUpTailTerms();
287      }
288    }
289
290    /// Destructor should not destruct the resulting m_syzLeads, m_syzTails.
291    ~SchreyerSyzygyComputation(){ CleanUp(); }
292
293    /// Convert the given ideal of tails into the internal representation (with reducers!)
294    /// Preprocess m_idTails as well...?
295    void SetUpTailTerms();
296
297    /// print statistics about the used heuristics
298    void PrintStats() const;
299
300    /// Read off the results while detaching them from this object
301    /// NOTE: no copy!
302    inline void ReadOffResult(ideal& syzL, ideal& syzT)
303    {
304      syzL = m_syzLeads; syzT = m_syzTails;
305
306      m_syzLeads = m_syzTails = NULL; // m_LS ?
307     
308      if ( __PROT__ )
309        PrintStats();
310    }
311
312
313    /// The main driver function: computes
314    void ComputeSyzygy();
315
316    /// Computes Syz(leads) or only LEAD of it.
317    /// The result is stored into m_syzLeads
318    void ComputeLeadingSyzygyTerms(bool bComputeSecondTerms = true);
319
320    poly SchreyerSyzygyNF(const poly syz_lead, poly syz_2 = NULL) const;
321
322    /// High level caching function!!!
323    poly TraverseTail(poly multiplier, const int tail) const;
324
325    // REMOVE?
326    /// called only from above and from outside (for testing)
327    poly TraverseTail(poly multiplier, poly tail) const;
328
329    /// TODO: save shortcut (syz: |-.->) LM(m) * "t" -> ? ???
330    poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const;
331
332    /// low level computation...
333    poly ComputeImage(poly multiplier, const int tail) const;
334
335    //
336    poly TraverseNF(const poly syz_lead, const poly syz_2 = NULL) const;
337
338
339  public:
340    /// just for testing via the wrapper below
341    inline poly _FindReducer(const poly product, const poly syzterm) const
342        { return m_div.FindReducer(product, syzterm, m_checker); }
343 private:
344    void CleanUp();
345  protected:
346
347
348    /// just leading terms
349    ideal Compute1LeadingSyzygyTerms();
350
351    /// leading + second terms
352    ideal Compute2LeadingSyzygyTerms();
353
354   
355
356  private:
357    /// input leading terms
358    const ideal m_idLeads;
359
360    /// input tails
361    const ideal m_idTails;
362
363    /// output (syzygy) leading terms (+2nd terms?)
364    ideal m_syzLeads;
365
366    /// output (syzygy) tails
367    ideal m_syzTails;
368
369    /*mutable?*/ ideal m_LS; ///< leading syzygy terms used for reducing syzygy tails
370
371
372    /// Bitmask for variables occuring in leading terms
373    const CLCM m_lcm;
374
375    /// Divisor finder
376    const CReducerFinder m_div;
377
378    /// for checking tail-terms and makeing them irreducible (wrt m_LS!)
379    CReducerFinder m_checker;
380
381    /*
382    // need more data here:
383    // (m_idLeads : m_tailterm) = (m, pos, compl), s.th: compl * m_tailterm divides m_idLeads[pos]
384    // but resulting sysygy compl * gen(pos) should not be in
385    // Idea: extend CReducerFinder??!!
386    struct CTailTerm
387    {
388      const poly m_tailterm;
389
390      const CReducerFinder m_reducers; // positions are labels (in m_idLeads)...
391      // compl - to be computed if needed?
392
393      CTailTerm(const poly tt, const CReducerFinder reds): m_tailterm(tt), m_reducers(reds) {}
394    };
395
396    typedef std::vector<const CTailTerm*> TTail;
397    typedef std::vector<TTail> TTailTerms;
398
399    TTailTerms m_idTailTerms;
400    */
401
402    mutable TCache m_cache; // cacher comp + poly -> poly! // mutable???
403
404/// TODO: look into m_idTailTerms!!!!!!!!!!!!!!!!!!!!!!!! map? heaps???
405    // NOTE/TODO: the following globally shared buckets violate reentrance - they should rather belong to TLS!
406
407    /// used for simple summing up
408    mutable sBucket_pt m_sum_bucket;
409
410    /// for S-Polynomial reductions
411    mutable kBucket_pt m_spoly_bucket;
412};
413
414   
415    /// Statistics:
416    ///  0..3: as in SetUpTailTerms()::PreProcessTerm() // TODO!!??
417    ///  4: number of terms discarded due to LOT heuristics
418    ///  5: number of terms discarded due to LCM heuristics
419    ///  6, 7: lookups without & with rescale, 8: stores
420    mutable unsigned long m_stat[9];
421};
422
423// The following wrappers are just for testing separate functions on highest level (within schreyer.lib)
424
425static inline void ComputeSyzygy(const ideal L, const ideal T, ideal& LL, ideal& TT, const SchreyerSyzygyComputationFlags A)
426{
427  SchreyerSyzygyComputation syz(L, T, A);
428  syz.ComputeSyzygy();
429  syz.ReadOffResult(LL, TT);
430}
431
432static inline ideal ComputeLeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A)
433{
434  SchreyerSyzygyComputation syz(L, NULL, A);
435  syz.ComputeLeadingSyzygyTerms(false);
436  ideal LL, TT;
437  syz.ReadOffResult(LL, TT);
438  return LL; // assume TT is NULL!
439}
440
441static inline ideal Compute2LeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A)
442{
443  SchreyerSyzygyComputation syz(L, NULL, A);
444  syz.ComputeLeadingSyzygyTerms(true);
445  ideal LL, TT;
446  syz.ReadOffResult(LL, TT);
447  return LL; // assume TT is NULL!
448}
449
450static inline poly FindReducer(poly product, poly syzterm,
451                               ideal L, ideal LS, const SchreyerSyzygyComputationFlags A)
452{
453  SchreyerSyzygyComputation syz(L, NULL, LS, A);
454  return syz._FindReducer(product, syzterm);
455}
456
457static inline poly TraverseTail(poly multiplier, poly tail,
458                                ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
459{
460  SchreyerSyzygyComputation syz(L, T, LS, A);
461  return syz.TraverseTail(multiplier, tail);
462}
463
464static inline poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck,
465                              ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
466{
467  SchreyerSyzygyComputation syz(L, T, LS, A);
468  return syz.ReduceTerm(multiplier, term4reduction, syztermCheck);
469}
470
471
472static inline poly SchreyerSyzygyNF(poly syz_lead, poly syz_2,
473                                    ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
474{
475  SchreyerSyzygyComputation syz(L, T, LS, A);
476  return syz.SchreyerSyzygyNF(syz_lead, syz_2);
477}
478
479END_NAMESPACE
480
481END_NAMESPACE_SINGULARXX
482
483#endif
484/* #ifndef SYZEXTRA_H */
485
486// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
487
Note: See TracBrowser for help on using the repository browser.