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

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