1 /*
2 4ti2 -- A software package for algebraic, geometric and combinatorial
3 problems on linear spaces.
4 
5 Copyright (C) 2006 4ti2 team.
6 Main author(s): Matthias Walter.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22 
23 #ifndef _4ti2_zsolve__Variables_
24 #define _4ti2_zsolve__Variables_
25 
26 #include <iostream>
27 #include <vector>
28 #include <cassert>
29 
30 #include "zsolve/Integer.h"
31 
32 namespace _4ti2_zsolve_
33 {
34 
35 template <typename T> class VariableProperty
36 {
37 protected:
38     int m_column_id;
39     bool m_is_free;
40     T m_upper_bound;
41     T m_lower_bound;
42 
43 public:
VariableProperty(const int column,const bool free,const T & lower,const T & upper)44     VariableProperty (const int column, const bool free, const T& lower, const T& upper)
45     {
46         set (column, free, lower, upper);
47     }
48 
VariableProperty(const VariableProperty & other)49     VariableProperty (const VariableProperty& other)
50     {
51         set (other.m_column_id, other.m_is_free, other.m_lower_bound, other.m_upper_bound);
52     }
53 
is_symmetric() const54     bool is_symmetric () const
55     {
56         return m_upper_bound + m_lower_bound == 0;
57     }
58 
set_bound(bool set_lower,const T & value)59     void set_bound (bool set_lower, const T& value)
60     {
61         if (m_is_free)
62             return;
63 
64         if (set_lower)
65             m_lower_bound = value;
66         else
67             m_upper_bound = value;
68     }
69 
set(const VariableProperty & other)70     void set (const VariableProperty& other)
71     {
72         set (other.m_column_id, other.m_is_free, other.m_lower_bound, other.m_upper_bound);
73     }
74 
set(const int column,const bool free,const T & lower,const T & upper)75     void set (const int column, const bool free, const T& lower, const T& upper)
76     {
77         m_column_id = column;
78         m_is_free = free;
79         m_lower_bound = lower;
80         m_upper_bound = upper;
81 
82     }
83 
set(const bool free,const T & lower=1,const T & upper=-1)84     void set (const bool free, const T& lower = 1, const T& upper = -1)
85     {
86         m_is_free = free;
87         m_lower_bound = lower;
88         m_upper_bound = upper;
89     }
90 
setSign(int sign)91     void setSign (int sign)
92     {
93 	if (sign == 2)
94 	{
95 	    m_is_free = false;
96 	    if (m_lower_bound == 0)
97 		m_lower_bound = 1;
98 	    if (m_upper_bound == 0)
99 		m_upper_bound = -1;
100 	}
101 	else if (sign == 1)
102 	{
103 	    m_is_free = false;
104 	    m_lower_bound = 0;
105 	    if (m_upper_bound == 0)
106 		m_upper_bound = -1;
107 	}
108 	else if (sign == -1)
109 	{
110 	    m_is_free = false;
111 	    m_upper_bound = 0;
112 	    if (m_lower_bound == 0)
113 		m_lower_bound = 1;
114 	}
115 	else
116 	    set (true, 1, -1);
117     }
118 
sign()119     int sign ()
120     {
121 	if (m_is_free)
122 	    return 0;
123 	if ((m_lower_bound == 0 && m_upper_bound == 0) || (m_lower_bound != 0 && m_upper_bound != 0))
124 	    return 2;
125 	else if (m_lower_bound == 0)
126 	    return 1;
127 	else
128 	    return -1;
129     }
130 
setLower(const T & lower)131     void setLower (const T& lower)
132     {
133 	if (lower <= 0)
134 	    m_is_free = false;
135 	m_lower_bound = lower;
136     }
137 
setUpper(const T & upper)138     void setUpper (const T& upper)
139     {
140         if (upper >= 0)
141             m_is_free = false;
142         m_upper_bound = upper;
143     }
144 
free() const145     bool free () const
146     {
147         return m_is_free;
148     }
149 
column() const150     int column () const
151     {
152         return m_column_id;
153     }
154 
lower() const155     T lower () const
156     {
157         return m_lower_bound;
158     }
159 
upper() const160     T upper () const
161     {
162         return m_upper_bound;
163     }
164 
compare(const VariableProperty & other) const165     int compare (const VariableProperty& other) const
166     {
167         int max = (m_column_id > other.m_column_id ? m_column_id : other.m_column_id) + 1;
168         int c1 = m_column_id < 0 ? max - m_column_id : m_column_id;
169         int c2 = other.m_column_id < 0 ? max - other.m_column_id : other.m_column_id;
170 
171         return c1 - c2;
172     }
173 
count_infinity() const174     int count_infinity () const
175     {
176         int result = 2;
177         if (m_lower_bound <= 0)
178             result--;
179         if (m_upper_bound >= 0)
180             result--;
181         return result;
182     }
183 
get_range()184     T get_range ()
185     {
186         T result = 0;
187         if (m_upper_bound > 0)
188             result += m_upper_bound;
189         if (m_lower_bound < 0)
190             result -= m_lower_bound;
191         return result;
192     }
193 
check_bounds(const T & value)194     bool check_bounds (const T& value)
195     {
196         if (m_lower_bound <= 0 && value < m_lower_bound)
197             return false;
198         if (m_upper_bound >= 0 && value > m_upper_bound)
199             return false;
200         return true;
201     }
202 
check_consistency() const203     bool check_consistency () const
204     {
205         return m_column_id >= -2;
206     }
207 
lower_space() const208     int lower_space () const
209     {
210         return m_lower_bound < 0 ? integer_space (m_lower_bound) : 1;
211     }
212 
upper_space() const213     int upper_space () const
214     {
215         return m_upper_bound > 0 ? integer_space (m_upper_bound) : 1;
216     }
217 
upper(std::ostream & out) const218     std::ostream& upper (std::ostream& out) const
219     {
220         if (m_upper_bound >= 0)
221             out << m_upper_bound;
222         else
223             out << "+";
224         return out;
225     }
226 
lower(std::ostream & out) const227     std::ostream& lower (std::ostream& out) const
228     {
229         if (m_lower_bound <= 0)
230             out << m_lower_bound;
231         else
232             out << "-";
233         return out;
234     }
235 
dump(std::ostream & out) const236     std::ostream& dump (std::ostream& out) const
237     {
238         out << m_column_id;
239         out << (m_is_free ? " 1 " : " 0 ");
240         out << m_lower_bound;
241         out << " ";
242         out << m_upper_bound;
243         return out;
244     }
245 };
246 
247 template <typename T> class VariableProperties
248 {
249 protected:
250     std::vector <VariableProperty <T> *> m_variable_properties;
251 
252 public:
VariableProperties(size_t variables,bool free,const T & lower,const T & upper)253     VariableProperties (size_t variables, bool free, const T& lower, const T& upper)
254     {
255         m_variable_properties.resize (variables);
256         for (size_t i = 0; i < variables; i++)
257         {
258             m_variable_properties[i] = new VariableProperty <T> (i, free, lower, upper);
259         }
260     }
261 
VariableProperties(VariableProperties<T> * other)262     VariableProperties (VariableProperties <T>* other)
263     {
264         m_variable_properties.resize (other->variables ());
265         for (size_t i = 0; i < other->variables (); i++)
266         {
267             m_variable_properties[i] = new VariableProperty <T> (other->get_variable (i));
268         }
269     }
270 
~VariableProperties()271     ~VariableProperties ()
272     {
273         for (size_t i = 0; i < m_variable_properties.size (); i++)
274             delete m_variable_properties[i];
275         m_variable_properties.clear ();
276     }
277 
get_variable(size_t index)278     VariableProperty <T>& get_variable (size_t index)
279     {
280         return *m_variable_properties[index];
281     }
282 
variables() const283     size_t variables () const
284     {
285         return m_variable_properties.size ();
286     }
287 
swap(size_t a,size_t b)288     void swap (size_t a, size_t b)
289     {
290         VariableProperty <T> * temp = m_variable_properties[a];
291         m_variable_properties[a] = m_variable_properties[b];
292         m_variable_properties[b] = temp;
293     }
294 
check_consistency() const295     bool check_consistency () const
296     {
297         for (size_t i = 0; i < m_variable_properties.size (); i++)
298             if (!m_variable_properties[i].check_consistency ())
299                 return false;
300         return true;
301     }
302 };
303 
304 } // namespace _4ti2_zsolve_
305 
306 #endif
307