source: git/dyn_modules/syzextra/syzextra.h @ 0838d7

spielwiese
Last change on this file since 0838d7 was 0838d7, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Reuse s/k-buckets + removal of CPolynomialSummator chg: do not explicitly compute length for bucket addition
  • Property mode set to 100644
File size: 12.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__), m_rBaseRing(attr.m_rBaseRing)
69    {}   
70
71  /// output all the intermediate states
72  const int __DEBUG__; // DebugOutput;
73
74  //  const bool __SYZCHECK__; // CheckSyzygyProperty: never tested here...
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  const int __SYZNUMBER__; 
92 
93  /// global base ring
94  const ring m_rBaseRing;
95};
96
97class SchreyerSyzygyComputation;
98
99class CLCM: public SchreyerSyzygyComputationFlags, public std::vector<bool>
100{
101  public:
102    CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags);
103
104    bool Check(const poly m) const;
105   
106  private:
107    bool m_compute;
108
109    const unsigned int m_N; ///< number of ring variables
110};
111
112
113class CLeadingTerm
114{
115  public: 
116    CLeadingTerm(unsigned int label,  const poly lt, const ring);
117
118  public:
119
120    const unsigned long m_sev; ///< not short exp. vector
121        // NOTE/TODO: either of the following should be enough:
122    const unsigned int  m_label; ///< index in the main L[] + 1
123    const poly          m_lt; ///< the leading term itself L[label-1]
124
125  public:
126    bool DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const;
127    bool DivisibilityCheck(const poly multiplier, const poly t, const unsigned long not_sev, const ring r) const;
128
129  private:
130    // disable the following:
131    CLeadingTerm();
132    CLeadingTerm(const CLeadingTerm&);
133    void operator=(const CLeadingTerm&);
134};
135
136
137// TODO: needs a specialized variant without a component (hash!)
138class CReducerFinder: public SchreyerSyzygyComputationFlags
139{
140  friend class CDivisorEnumerator;
141  friend class CDivisorEnumerator2;
142  private:
143    typedef long TComponentKey;
144    typedef std::vector<const CLeadingTerm*> TReducers;
145    typedef std::map< TComponentKey, TReducers> CReducersHash;
146
147  public:
148    /// goes over all leading terms
149    CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags);
150
151    void Initialize(const ideal L);
152
153    ~CReducerFinder();
154
155    // TODO: save shortcut (syz: |-.->) LM(LM(m) * "t") -> syz?
156    poly // const_iterator // TODO: return const_iterator it, s.th: it->m_lt is the needed
157    FindReducer(const poly product, const poly syzterm, const CReducerFinder& checker) const;
158
159    bool IsDivisible(const poly q) const;
160
161    inline bool IsNonempty() const { return !m_hash.empty(); }
162
163    /// is the term to be "preprocessed" as lower order term or lead to only reducible syzygies...
164    int PreProcessTerm(const poly t, CReducerFinder& syzChecker) const;
165
166    poly FindReducer(const poly multiplier, const poly monom, const poly syzterm, const CReducerFinder& checker) const;
167   
168#ifndef NDEBUG
169    void DebugPrint() const;
170#endif
171   
172  private:
173    ideal m_L; ///< only for debug
174
175    CReducersHash m_hash; // can also be replaced with a vector indexed by components
176
177  private:
178    CReducerFinder(const CReducerFinder&);
179    void operator=(const CReducerFinder&);
180};
181
182extern ideal id_Copy (const ideal, const ring);
183
184
185/** @class SchreyerSyzygyComputation syzextra.h
186 *
187 * Computing syzygies after Schreyer
188 *
189 * Storing/accumulating data during the computation requires some global
190 * object, like this class. Ideally the above global functions should not
191 * be used in favour of this class.
192 *
193 * @sa Schreyer Syzygy Computation Paper & Talk & Python prototype
194 */
195class SchreyerSyzygyComputation: public SchreyerSyzygyComputationFlags
196{
197  friend class CLCM;
198  friend class CReducerFinder;
199 
200  public:
201    /// Construct a global object for given input data (separated into leads & tails)
202    SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const SchreyerSyzygyComputationFlags setting):
203        SchreyerSyzygyComputationFlags(setting),
204        m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)), 
205        m_syzLeads(NULL), m_syzTails(NULL),
206        m_LS(NULL), m_lcm(m_idLeads, setting), 
207        m_div(m_idLeads, setting), m_checker(NULL, setting),
208        m_sum_bucket(NULL), m_spoly_bucket(NULL)
209    {
210    }
211
212    /// Construct a global object for given input data (separated into leads & tails)
213    SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const ideal syzLeads, const SchreyerSyzygyComputationFlags setting):
214        SchreyerSyzygyComputationFlags(setting),
215        m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)), 
216        m_syzLeads(syzLeads), m_syzTails(NULL),
217        m_LS(syzLeads), m_lcm(m_idLeads, setting), 
218        m_div(m_idLeads, setting), m_checker(NULL, setting),
219        m_sum_bucket(NULL), m_spoly_bucket(NULL)
220    {
221      if( __TAILREDSYZ__ && !__IGNORETAILS__)
222      {
223        if (syzLeads != NULL)
224          m_checker.Initialize(syzLeads);
225//        if( idTails != NULL )
226//          SetUpTailTerms();
227      }
228    }
229
230    /// Destructor should not destruct the resulting m_syzLeads, m_syzTails.
231    ~SchreyerSyzygyComputation(){ CleanUp(); } 
232
233    /// Convert the given ideal of tails into the internal representation (with reducers!)
234    /// Preprocess m_idTails as well...?
235    void SetUpTailTerms();
236   
237    /// Read off the results while detaching them from this object
238    /// NOTE: no copy!
239    inline void ReadOffResult(ideal& syzL, ideal& syzT)
240    {
241      syzL = m_syzLeads; syzT = m_syzTails; 
242
243      m_syzLeads = m_syzTails = NULL; // m_LS ?
244    }
245   
246    /// The main driver function: computes
247    void ComputeSyzygy();
248
249    /// Computes Syz(leads) or only LEAD of it.
250    /// The result is stored into m_syzLeads
251    void ComputeLeadingSyzygyTerms(bool bComputeSecondTerms = true);
252
253    poly SchreyerSyzygyNF(const poly syz_lead, poly syz_2 = NULL) const;
254
255    poly TraverseTail(poly multiplier, const int tail) const;
256
257    // called only from above and from outside (for testing)
258    poly TraverseTail(poly multiplier, poly tail) const;
259
260    // TODO: save shortcut (syz: |-.->) LM(m) * "t" -> ?
261    poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const;
262
263    //
264    poly TraverseNF(const poly syz_lead, const poly syz_2 = NULL) const;
265
266   
267  public:
268    /// just for testing via the wrapper below
269    inline poly _FindReducer(const poly product, const poly syzterm) const
270        { return m_div.FindReducer(product, syzterm, m_checker); } 
271 private:
272    void CleanUp();
273  protected:
274
275
276    /// just leading terms
277    ideal Compute1LeadingSyzygyTerms();
278
279    /// leading + second terms
280    ideal Compute2LeadingSyzygyTerms();
281
282  private:
283    /// input leading terms
284    const ideal m_idLeads;
285
286    /// input tails
287    const ideal m_idTails;
288
289    /// output (syzygy) leading terms (+2nd terms?)
290    ideal m_syzLeads;
291
292    /// output (syzygy) tails
293    ideal m_syzTails;
294   
295    /*mutable?*/ ideal m_LS; ///< leading syzygy terms used for reducing syzygy tails
296
297
298    /// Bitmask for variables occuring in leading terms
299    const CLCM m_lcm;
300
301    /// Divisor finder
302    const CReducerFinder m_div;
303
304    /// for checking tail-terms and makeing them irreducible (wrt m_LS!)
305    CReducerFinder m_checker;
306
307    /*
308    // need more data here:
309    // (m_idLeads : m_tailterm) = (m, pos, compl), s.th: compl * m_tailterm divides m_idLeads[pos]
310    // but resulting sysygy compl * gen(pos) should not be in
311    // Idea: extend CReducerFinder??!!
312    struct CTailTerm
313    {
314      const poly m_tailterm;
315     
316      const CReducerFinder m_reducers; // positions are labels (in m_idLeads)...
317      // compl - to be computed if needed?
318
319      CTailTerm(const poly tt, const CReducerFinder reds): m_tailterm(tt), m_reducers(reds) {}
320    };
321
322    typedef std::vector<const CTailTerm*> TTail;
323    typedef std::vector<TTail> TTailTerms;
324   
325    TTailTerms m_idTailTerms;
326    */
327
328   
329/// TODO: look into m_idTailTerms!!!!!!!!!!!!!!!!!!!!!!!! map? heaps???
330    // NOTE/TODO: the following globally shared buckets violate reentrance - they should rather belong to TLS!
331   
332    /// used for simple summing up
333    mutable sBucket_pt m_sum_bucket;
334   
335    /// for S-Polynomial reductions
336    mutable kBucket_pt m_spoly_bucket;
337};
338
339
340// The following wrappers are just for testing separate functions on highest level (within schreyer.lib)
341
342static inline void ComputeSyzygy(const ideal L, const ideal T, ideal& LL, ideal& TT, const SchreyerSyzygyComputationFlags A)
343{
344  SchreyerSyzygyComputation syz(L, T, A);
345  syz.ComputeSyzygy();
346  syz.ReadOffResult(LL, TT);
347}
348
349static inline ideal ComputeLeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A)
350{
351  SchreyerSyzygyComputation syz(L, NULL, A);
352  syz.ComputeLeadingSyzygyTerms(false);
353  ideal LL, TT;
354  syz.ReadOffResult(LL, TT);
355  return LL; // assume TT is NULL!
356}
357
358static inline ideal Compute2LeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A)
359{
360  SchreyerSyzygyComputation syz(L, NULL, A);
361  syz.ComputeLeadingSyzygyTerms(true);
362  ideal LL, TT;
363  syz.ReadOffResult(LL, TT);
364  return LL; // assume TT is NULL!
365}
366
367static inline poly FindReducer(poly product, poly syzterm,
368                               ideal L, ideal LS, const SchreyerSyzygyComputationFlags A)
369{
370  SchreyerSyzygyComputation syz(L, NULL, LS, A);
371  return syz._FindReducer(product, syzterm);
372}
373
374static inline poly TraverseTail(poly multiplier, poly tail, 
375                                ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
376{
377  SchreyerSyzygyComputation syz(L, T, LS, A);
378  return syz.TraverseTail(multiplier, tail);
379}
380
381static inline poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck,
382                              ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
383{
384  SchreyerSyzygyComputation syz(L, T, LS, A);
385  return syz.ReduceTerm(multiplier, term4reduction, syztermCheck);
386}
387
388
389static inline poly SchreyerSyzygyNF(poly syz_lead, poly syz_2,
390                                    ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A)
391{
392  SchreyerSyzygyComputation syz(L, T, LS, A);
393  return syz.SchreyerSyzygyNF(syz_lead, syz_2);
394}
395
396END_NAMESPACE
397   
398END_NAMESPACE_SINGULARXX
399
400#endif
401/* #ifndef SYZEXTRA_H */
402
403// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
404
Note: See TracBrowser for help on using the repository browser.