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): Peter Malkin.
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 #include "WalkAlgorithm.h"
24 #include "Completion.h"
25 #include "VectorStream.h"
26 #include "VectorArrayStream.h"
27 #include "BinomialSet.h"
28 #include "BinomialSetStream.h"
29 #include "FlipCompletion.h"
30 #include "BinomialFactory.h"
31 #include "Globals.h"
32 
33 #include <iostream>
34 #include <iomanip>
35 #include <cstdlib>
36 
37 //#define DEBUG_4ti2(X) X
38 #include "Debug.h"
39 
40 using namespace _4ti2_;
41 
WalkAlgorithm()42 WalkAlgorithm::WalkAlgorithm()
43 {
44     costnew_start = 0;
45     costnew_end = 0;
46     costold_start = 0;
47     costold_end = 0;
48 }
49 
~WalkAlgorithm()50 WalkAlgorithm::~WalkAlgorithm()
51 {
52 }
53 
54 void
compute(Feasible & feasible,const VectorArray & costold,VectorArray & vs,const VectorArray & costnew)55 WalkAlgorithm::compute(
56                 Feasible& feasible,
57                 const VectorArray& costold,
58                 VectorArray& vs,
59                 const VectorArray& costnew)
60 {
61     DEBUG_4ti2(*out << "Cost1:\n" << costold << "\n";)
62     DEBUG_4ti2(*out << "Cost2:\n" << costnew << "\n";)
63     DEBUG_4ti2(*out << "VS:\n" << vs << "\n";)
64     assert(costold.get_number() > 0 && costnew.get_number() > 0);
65     t.reset();
66 
67     // TODO: We might need to add cost vectors to the old and new costs.
68     VectorArray costall(costnew);
69     costall.insert(costold);
70 
71     BinomialFactory factory(feasible, costall);
72 
73     costnew_start = Binomial::cost_start;
74     costnew_end = Binomial::cost_start+costnew.get_number();
75     costold_start = costnew_end;
76     costold_end = Binomial::cost_end;
77 
78     BinomialSet bs;
79     factory.convert(vs, bs, false);
80 
81     TermOrder term_order(costnew_start, costnew_end, Binomial::rs_end);
82 
83     // TODO: Perhaps the following value should be an command line option.
84     const int reduction_freq = 200;
85 
86     int iteration = 0;
87     DEBUG_4ti2(*out << "\nBefore BINOMIALS:\n" << bs << "\n";)
88     int n;
89     Binomial b;
90     FlipCompletion alg;
91     while(!next(bs, term_order, n))
92     {
93         if (iteration % Globals::output_freq == 0)
94         {
95             *out << "\r";
96             *out << std::setiosflags(std::ios_base::right);
97             *out << "Iteration = " << std::setw(6) << iteration;
98             *out << " Size = " << std::setw(6) << bs.get_number();
99             *out << " tvalue " << std::setw(6) << std::setprecision(4);
100             *out << std::resetiosflags(std::ios_base::right);
101             *out << std::setiosflags(std::ios_base::left);
102             *out << tvalue(bs[n]) << std::flush;
103             *out << std::resetiosflags(std::ios_base::left);
104         }
105         DEBUG_4ti2(*out << "Iteration " << iteration << "\n";)
106         DEBUG_4ti2(*out << "\nBefore BINOMIALS:\n" << bs << "\n";)
107         b = bs[n];
108         bs.remove(n);
109         if (!bs.reducable(b))
110         {
111             b.flip();
112             alg.algorithm(bs, b);
113             bs.add(b);
114             if (iteration % reduction_freq == 0)
115             { bs.minimal(); bs.reduced(); }
116             DEBUG_4ti2(*out << "Size: " << std::setw(6) << bs.get_number() << "\n";)
117             DEBUG_4ti2(*out << "After BINOMIALS:\n" << bs << "\n";)
118             ++iteration;
119         }
120     }
121     bs.minimal();
122     bs.reduced();
123     factory.convert(bs, vs);
124     vs.sort();
125     bs.clear();
126 
127     DEBUG_4ti2(*out << "VS:\n" << vs << "\n";)
128     *out << "\r" << Globals::context;
129     *out << "Iteration = " << std::setw(6) << iteration;
130     *out << " Size: " << std::setw(6) << vs.get_number();
131     *out << ", Time: " << t << " / ";
132     *out << Timer::global << " secs. Done." << std::endl;
133 }
134 
135 IntegerType
compare(const Binomial & b1,const Binomial & b2)136 WalkAlgorithm::compare(const Binomial& b1, const Binomial& b2)
137 {
138     IntegerType result;
139     for (int i = costnew_start; i < costnew_end; ++i)
140     {
141         for (int j = costold_start; j < costold_end; ++j)
142         {
143             result = b1[j]*b2[i]-b1[i]*b2[j];
144             if (result != 0) { return result; }
145         }
146         for (int j = 0; j < Binomial::rs_end; j++)
147         {
148             result = -b1[j]*b2[i]+b1[i]*b2[j];
149             if (result != 0) { return result; }
150         }
151     }
152     for (int i = 0; i < Binomial::rs_end; i++)
153     {
154         for (int j = costold_start; j < costold_end; ++j)
155         {
156             result = -b1[j]*b2[i]+b1[i]*b2[j];
157             if (result != 0) { return result; }
158         }
159         for (int j = 0; j < Binomial::rs_end; j++)
160         {
161             result = b1[j]*b2[i]-b1[i]*b2[j];
162             if (result != 0) { return result; }
163         }
164     }
165     std::cerr << "Software Error: unexpected execution.\n";
166     exit(1);
167     return 0;
168 }
169 
170 RationalType
tvalue(const Binomial & b)171 WalkAlgorithm::tvalue(const Binomial& b)
172 {
173     if (b[costold_start]-b[costnew_start] == 0)
174 	return 0;		// Avoid division by zero
175     else
176 	return (RationalType)b[costold_start]/(b[costold_start]-b[costnew_start]);
177 }
178 
179 void
tvector(Vector & c1,Vector & c2,Vector & v,Vector & tv)180 WalkAlgorithm::tvector(Vector& c1, Vector& c2, Vector& v, Vector& tv)
181 {
182     Vector::sub(c2, Vector::dot(c1,v), c1, Vector::dot(c2,v), tv);
183 }
184 
185 bool
next(const BinomialSet & bs,const TermOrder & term_order,int & min)186 WalkAlgorithm::next(const BinomialSet& bs, const TermOrder& term_order, int& min)
187 {
188     min = 0;
189     while (min < bs.get_number())
190     {
191         if (TermOrder::direction(term_order, bs[min]) < 0) { break; }
192         else { ++min; }
193     }
194     if (min == bs.get_number()) { return true; }
195     DEBUG_4ti2(*out << min << " tvalue = " << tvalue(bs[min]) << "\n";)
196     for (int i = min+1; i < bs.get_number(); ++i)
197     {
198         if (TermOrder::direction(term_order, bs[i]) < 0)
199         {
200             DEBUG_4ti2(*out << i << " tvalue = " << tvalue(bs[i]) << "\n";)
201             if (compare(bs[min], bs[i]) < 0) { min = i; }
202         }
203     }
204     DEBUG_4ti2(*out << min << " min tvalue = " << tvalue(bs[min]) << "\n";)
205     return false;
206 }
207