carl  24.04
Computer ARithmetic Library
GroebnerBase.tpp
Go to the documentation of this file.
1 /*
2  * File: GroebnerBase.tpp
3  * Author: tobias
4  *
5  * Created on 8. August 2016, 16:15
6  */
7 
8 #pragma once
9 
10 namespace carl {
11 
12 
13 template<typename Number>
14 bool GroebnerBase<Number>::hasFiniteMon() const {
15  std::set<Variable> vars = this->gatherVariables();
16  std::vector<typename GroebnerBase<Number>::Monomial> lmons = this->cor();
17  for (const auto& v: vars) {
18  bool found = true;
19  for (const auto& m : lmons) {
20  assert(is_one(m.coeff()));
21  if (m.has_no_other_variable(v)) {
22  found = false;
23  break;
24  }
25  }
26  if (found) return false;
27  }
28  return true;
29 }
30 
31 
32 template<typename Number>
33 std::vector<typename GroebnerBase<Number>::Monomial> GroebnerBase<Number>::cor() const {
34  std::vector<typename GroebnerBase<Number>::Monomial> res;
35  for(const auto& p : this->get()) {
36  res.push_back(GroebnerBase<Number>::Monomial(p.lmon()));
37  }
38  return res;
39 }
40 
41 // general helper function
42 // returns true iff any of the monomials in list divides m
43 template<typename Number>
44 bool anyDivides(const std::vector<typename GroebnerBase<Number>::Monomial>& list, const typename GroebnerBase<Number>::Monomial& m) {
45  CARL_LOG_ASSERT("carl.thom.groebner", is_one(m.coeff()), "invalid monomial!");
46  for(const auto& m_prime : list) {
47  CARL_LOG_ASSERT("carl.thom.groebner", is_one(m_prime.coeff()), "invalid monomial!");
48  if(m.divisible(m_prime)) {
49  return true;
50  }
51  }
52  return false;
53 }
54 
55 }
56 
57 // this is a helper function for mon
58 template<typename Number> // i dont know why this has to be a template but i get a linker error if its not
59 bool nextTuple(std::vector<carl::uint>& tuple, const std::vector<carl::uint>& maxTuple) {
60  assert(tuple.size() == maxTuple.size());
61  if(tuple[0] < maxTuple[0]) {
62  tuple[0]++;
63  return true;
64  }
65  else {
66  assert(tuple[0] == maxTuple[0]);
67  bool succes = false;
68  for(carl::uint i = 1; i < tuple.size(); i++) {
69  if(tuple[i] < maxTuple[i]) {
70  for(carl::uint j = 0; j < i; j++) tuple[j] = 0;
71  tuple[i]++;
72  succes = true;
73  break;
74  }
75  }
76  return succes;
77  }
78 }
79 
80 namespace carl {
81 
82 template<typename Number>
83 std::vector<typename GroebnerBase<Number>::Monomial> GroebnerBase<Number>::mon() const {
84  CARL_LOG_FUNC("carl.thom.groebner", "groebner base: " << this->get());
85  CARL_LOG_ASSERT("carl.thom.groebner", this->hasFiniteMon(), "tried to compute mon of non-zerodimensional system");
86  std::set<Variable> varsset = this->gatherVariables();
87  std::vector<Variable> vars(varsset.begin(), varsset.end());
88  std::vector<typename GroebnerBase<Number>::Monomial> lmons = this->cor();
89  std::vector<uint> degrees;
90  for(const auto& v : vars) {
91  for(const auto& m : lmons) {
92  CARL_LOG_ASSERT("carl.thom.groebner", is_one(m.coeff()), "invalid monomial!");
93  if(m.has_no_other_variable(v)) {
94  degrees.push_back(m.monomial()->tdeg());
95  break;
96  }
97  }
98  }
99  CARL_LOG_ASSERT("carl.thom.groebner", degrees.size() == vars.size(), "");
100  CARL_LOG_TRACE("carl.thom.groebner", "variables: " << vars);
101  CARL_LOG_TRACE("carl.thom.groebner", "vector of degrees: " << degrees);
102 
103  std::vector<typename GroebnerBase<Number>::Monomial> res;
104  std::vector<uint> currTuple(degrees.size(), 0);
105  do {
106  typename GroebnerBase<Number>::Monomial candidate(Number(1));
107  for(uint i = 0; i < currTuple.size(); i++) {
108  for(uint d = 0; d < currTuple[i]; d++) {
109  candidate = candidate * vars[i];
110  }
111  }
112  if(!anyDivides<Number>(lmons, candidate)) {
113  res.push_back(candidate);
114  }
115  }
116  while(::nextTuple<Number>(currTuple, degrees));
117  CARL_LOG_TRACE("carl.thom.groebner", "result: " << res);
118  return res;
119 }
120 
121 template<typename Number>
122 std::vector<typename GroebnerBase<Number>::Monomial> GroebnerBase<Number>::bor() const {
123  std::vector<typename GroebnerBase<Number>::Monomial> res;
124  std::vector<typename GroebnerBase<Number>::Monomial> lmons = this->cor();
125  std::set<Variable> vars = this->gatherVariables();
126  std::vector<typename GroebnerBase<Number>::Monomial> _mon = this->mon();
127  for(const Variable& v : vars) {
128  for(const auto& m : _mon) {
129  assert(is_one(m.coeff()));
130  typename GroebnerBase<Number>::Monomial currMon = m * v;
131  if(std::find(res.begin(), res.end(), currMon) == res.end()) { // not already contained in res
132  if(std::find(_mon.begin(), _mon.end(), currMon) == _mon.end()) { // not contained in _mon
133  res.push_back(currMon);
134  }
135  }
136  }
137  }
138  return res;
139 }
140 
141 template<typename Number>
142 std::set<Variable> GroebnerBase<Number>::gatherVariables() const {
143  carlVariables vars;
144  for(const auto& p : this->get()) {
145  carl::variables(p, vars);
146  }
147  return vars.as_set();
148 }
149 
150 
151 } // namespace carl