Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
Simplex.H
1 
2 # ifndef SIMPLEX_H
3 # define SIMPLEX_H
4 
5 # include <limits>
6 # include <fstream>
7 # include <tpl_dynMat.H>
8 # include <tpl_dynDlist.H>
9 # include <format.H>
10 
11 namespace Aleph {
12 
13 
36 template <typename T> class Simplex
37 {
38 public:
39 
41  enum State { Not_Solved, Solving, Unbounded, Solved, Unfeasible };
42 
43 private:
44 
45 
46  // selecciona la celda de la función objetivo con menor
47  // valor. Retorna -1 si todas las celdas son negativas
48 
49  int compute_pivot_col() const
50  {
51  T minimum = numeric_limits<T>::max();
52  int p = -1;
53  for (int i = 0, M = num_var + num_rest; i < M; i++)
54  {
55  const T & c = m->read(0, i);
56  if (c < minimum)
57  {
58  p = i;
59  minimum = c;
60  }
61  }
62  return minimum >= 0 ? -1 : p;
63  }
64 
65  // selecciona entre los elementos B el menor valor de división
66  // entre el col_idx coeficiente de la función objetivo que
67  // sea positivo
68 
69  int compute_pivot_row(int p) const
70  {
71 
72  I(p >= 0 and p < num_var + num_rest);
73 
74  int q = -1;
75  T min_ratio = numeric_limits<T>::max();
76  for (int i = q + 1, M = num_var + num_rest; i <= num_rest; i++)
77  {
78  const T val = m->read(i, M);
79  if (val < 0)
80  continue;
81 
82  const T den = m->read(i, p);
83  if (den <= 0)
84  continue;
85 
86  const T ratio = val / den;
87  if (ratio < min_ratio)
88  {
89  q = i;
90  min_ratio = ratio;
91  }
92  }
93  return q;
94  }
95  State select_pivot(int & p, int & q)
96  {
97 
98  I(state == Not_Solved or state == Solving);
99 
100  const int col = compute_pivot_col();
101  if (col == -1)
102  return state = Solved;
103 
104  const int row = compute_pivot_row(col);
105  if (row == -1)
106  return state = Unbounded;
107 
108  p = row;
109  q = col;
110 
111  return state = Solving;
112  }
113  void to_pivot(size_t p, size_t q)
114  {
115 
116  I(p <= num_rest and q <= num_var + num_rest);
117 
118  const int M = num_var + num_rest; // cantidad de columnas
119  const T pivot = m->read(p, q);
120  for (int j = 0; j <= M; j++) // fila del pivote
121  if (j != q)
122  m->write(p, j, m->read(p, j) / pivot);
123 
124  m->write(p, q, 1);
125 
126  for (int i = 0; i <= num_rest; i++) // resto de las filas
127  for (int j = 0; j <= M; j++)
128  if (i != p and j != q)
129  m->write(i, j, m->read(i,j) - m->read(i,q)*m->read(p,j));
130 
131  for (int i = 0; i <= num_rest; i++) // col de pivote en 0 salvo q
132  if (i != p)
133  m->write(i, q, 0);
134  }
135  T find_value(const size_t j) const
136  {
137 
138  I(j < num_var);
139 
140  T ret_val = 0.0;
141  for (int i = 1, count = 0; i < num_rest; i++)
142  {
143  const T & value = m->read(i, j);
144  if (value == 0.0)
145  continue;
146 
147  if (value == 1.0)
148  if (count++ == 0)
149  ret_val = m->read(i, num_var + num_rest);
150  else
151  return 0.0;
152  else
153  return ret_val;
154  }
155  return ret_val;
156  }
157  DynMatrix<T> * m;
158 
159  T * objetive;
160 
161  DynDlist<T*> rest_list;
162 
163  int num_var;
164  int num_rest;
165 
166  T * solution;
167 
168  public:
169 
170  private:
171 
172  State state;
173 
174  void verify_var_index(int i)
175  {
176  if (i >= num_var)
177  throw std::out_of_range
178  (gnu::autosprintf("index %d out of range (%d max)", i, num_var - 1));
179  }
180 
181  T * create_restriction()
182  {
183  T * ptr = new T [num_var + 1];
184  rest_list.append(ptr);
185  num_rest++;
186  for (int i = 0; i <= num_var; i++)
187  ptr[i] = 0;
188  return ptr;
189  }
190 
191  void create_matrix()
192  {
193  m = new DynMatrix<T> (num_rest + 1, num_var + num_rest + 1);
194 
195  int i = 0; // llena los num_var coeficientes de la función objetivo
196  for (; i < num_var; i++)
197  m->write(0, i, -objetive[i]);
198 
199  // llena los num_var coeficientes de las restricciones
200  i = 1;
201  for (typename DynDlist<T*>::Iterator it(rest_list);
202  it.has_current(); it.next(), i++)
203  {
204  T * rest = it.get_current();
205 
206  for (int j = 0; j < num_var; j++)
207  m->write(i, j, rest[j]);
208 
209  m->write(i, num_var + i - 1, 1); // coef 1 i-esima variable slack
210 
211  m->write(i, num_var + num_rest, rest[num_var]);
212  }
213  }
214 
215 public:
216 
226  Simplex(int n)
227 
228  : m(NULL), objetive(NULL), num_var(n), num_rest(0), state(Not_Solved)
229  {
230  objetive = new T [num_var];
231  try
232  {
233  solution = new T [num_var];
234  }
235  catch (...)
236  {
237  delete objetive;
238  throw;
239  }
240  }
241 
244  void put_objetive_function_coef(int i, const T & coef)
245 
246  {
247  verify_var_index(i);
248  objetive[i] = coef;
249  }
250 
254  {
255  for (int i = 0; i < num_var; i++)
256  objetive[i] = coefs;
257  }
258 
261  void put_objetive_function(T coefs[])
262  {
263  for (int i = 0; i < num_var; i++)
264  objetive[i] = coefs;
265  }
279  T * put_restriction(T * coefs = NULL)
280 
281  {
282  T * rest = create_restriction();
283 
284  if (coefs == NULL)
285  return rest;
286 
287  for (int i = 0; i <= num_var; ++i)
288  rest[i] = coefs[i];
289 
290  return rest;
291  }
292 
294  T * get_restriction(int rest_num)
295 
296  {
297  if (rest_num >= num_rest)
298  throw std::out_of_range
299  (gnu::autosprintf("index %d out of range (%d max)",
300  rest_num, num_rest - 1));
301  int i = 1;
302  for (typename DynDlist<T*>::Iterator it(rest_list);
303  it.has_current(); it.next())
304  if (i == rest_num)
305  return it.get_current();
306  }
307 
321  {
322  T * rest = create_restriction();
323 
324  for (int i = 0; i <= num_var; ++i)
325  rest[i] = coefs[i];
326 
327  return rest;
328  }
329 
330  State latex_solve(char * name = NULL)
331  {
332  latex_matrix(gnu::autosprintf("%s-0.tex", name));
333  for (int i, j, k = 1; true; k++)
334  {
335  const Simplex<T>::State state = select_pivot(i, j);
336 
337  string str = gnu::autosprintf("%s-%d.tex", name, k);
338 
339  if (state == Simplex<T>::Unbounded or state == Simplex<T>::Solved)
340  {
341  latex_matrix(str.c_str());
342  return state;
343  }
344 
345  latex_matrix(str.c_str(), 2, i, j);
346  to_pivot(i, j);
347 
348  latex_matrix(name, i, j);
349  }
350  }
351 
366  {
367 
368  if (state != Not_Solved)
369  throw std::logic_error("solve() has already been called");
370  if (num_rest == 0)
371  throw std::logic_error("linear program without restrictions");
372 
373  for (int i, j; true;)
374  {
375  const Simplex<T>::State state = select_pivot(i, j);
376  if (state == Simplex<T>::Unbounded or state == Simplex<T>::Solved)
377  return state;
378 
379  to_pivot(i, j);
380  }
381  }
384  {
385  for (int j = 0; j < num_var; j++)
386  solution[j] = find_value(j);
387  }
388 
391  const T & get_solution(size_t i) const
392  {
393  I(i < num_var);
394  return solution[i];
395  }
396 
398  T objetive_value() const
399  {
400  T sum = 0;
401  for (int i = 0; i < num_var; i++)
402  sum += solution[i]*objetive[i];
403  return sum;
404  }
405 
408  bool verify_solution() const
409  {
410  for (typename DynDlist<T*>::Iterator it(rest_list);
411  it.has_current(); it.next())
412  {
413  T * rest = it.get_current();
414  T sum = 0;
415  for (int j = 0; j < num_var; j++)
416  sum += rest[j]*solution[j];
417 
418  if (sum > rest[num_var])
419  return false;
420  }
421  return true;
422  }
423 
424  void print_matrix()
425  {
426  for (int i = 0; i <= num_rest; ++i)
427  {
428  for (int j = 0; j <= num_var + num_rest; j++)
429  cout << float_f(m->read(i, j), 2) << " ";
430 
431  cout << endl;
432  }
433  }
434 
435  void latex_matrix(const char * name, int d = 2, int p = -1, int q = -1)
436  {
437  ofstream out(name, ios::out);
438 
439  const int cols = num_var + num_rest;
440 
441  out << "$\\left(\\begin{array}{c";
442  for (int i = 0; i < cols; i++)
443  out << "c";
444  out << "}" << endl;
445 
446  for (int i = 0; i <= num_rest; ++i)
447  {
448  for (int j = 0; j <= cols; j++)
449  {
450  if (i == p and j == q)
451  out << "\\circled{" << float_f(m->read(i, j), d) << "}" << " ";
452  else
453  out << float_f(m->read(i, j), d) << " ";
454  if (j != cols)
455  out << "& ";
456  }
457 
458  if (i != num_rest)
459  out << "\\\\";
460 
461  out << endl;
462  }
463  out << "\\end{array}\\right)$" << endl;
464  }
465 
466  void latex_linear_program(char * name)
467  {
468  ofstream out(name, ios::out);
469  out << "\\begin{equation*}" << endl
470  << "Z = " ;
471  for (int i = 0; i < num_var; i++)
472  {
473  if (objetive[i] == 0.0)
474  continue;
475 
476  if (i > 0)
477  out << " + ";
478 
479  if (objetive[i] != 1.0)
480  out << objetive[i];
481  out << "x_" << i;
482  }
483  out << endl
484  << "\\end{equation*}" << endl
485  << "Sujeto a:" << endl
486  << "\\begin{eqnarray*}" << endl;
487 
488  for (typename DynDlist<T*>::Iterator it(rest_list);
489  it.has_current(); it.next())
490  {
491  T * rest = it.get_current();
492 
493  for (int i = 0; i < num_rest; i++)
494  {
495  if (rest[i] == 0.0)
496  continue;
497 
498  if (i > 0)
499  out << " + ";
500 
501  if (rest[i] != 1.0)
502  out << rest[i];
503  out << " x_" << i;
504  }
505 
506  out << " & \\leq & " << rest[num_rest];
507 
508  if (not it.is_in_last())
509  out << " \\\\";
510 
511  out << endl;
512  }
513  out << "\\end{eqnarray*}" << endl;
514  }
515 
516  size_t get_num_restrictions() const { return num_rest; }
517 
518  size_t get_num_vars() const { return num_var; }
519 
520 
521  ~Simplex()
522  {
523  delete [] objetive;
524 
525  if (m != NULL)
526  delete m;
527  }
528 
529  T * get_objetive_function()
530  {
531  return objetive;
532  }
533 
535  T & get_restriction_coef(int rest_num, int idx)
536  {
537  verify_var_index(idx);
538 
539  return get_restriction(rest_num)[idx];
540  }
541 
542  void put_restriction_coef(int rest_num, int idx, const T & coef)
543  {
544  get_restriction_coef(rest_num, idx) = coef;
545  }
546 
547  void prepare_linear_program()
548  {
549  create_matrix();
550  }
551 };
552 
553 
554 } // end namespace Aleph
555 
556 # endif // SIMPLEX_H
557 
T * put_restriction(DynArray< T > &coefs)
Definition: Simplex.H:320
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Definition: ahAlgo.H:127
Definition: Simplex.H:36
T & get_restriction_coef(int rest_num, int idx)
retorna el coeficiente idx de la restricci{on rest_num
Definition: Simplex.H:535
void put_objetive_function(T coefs[])
Definition: Simplex.H:261
Definition: tpl_dynMat.H:43
State solve()
Definition: Simplex.H:365
T * get_restriction(int rest_num)
Retorna un punero al arreglo restricción num_rest.
Definition: Simplex.H:294
void put_objetive_function_coef(int i, const T &coef)
Definition: Simplex.H:244
T objetive_value() const
Retorna el valor de la función objetivo.
Definition: Simplex.H:398
void put_objetive_function(DynArray< T > &coefs)
Definition: Simplex.H:253
void load_solution()
Carga los valores de las variables solución.
Definition: Simplex.H:383
State
Estados del sistema.
Definition: Simplex.H:41
const T & get_solution(size_t i) const
Definition: Simplex.H:391
bool verify_solution() const
Definition: Simplex.H:408
Simplex(int n)
Definition: Simplex.H:226
Definition: tpl_dynArray.H:70
T * put_restriction(T *coefs=NULL)
Definition: Simplex.H:279
T & append(const T &item)
Definition: tpl_dynDlist.H:106

Leandro Rabindranath León