source: observatorio/simulacion/ModuloDinamico/io_manager.H

simulacion
Last change on this file was a0523b8, checked in by Alejandro <amujica@…>, 9 years ago

Correcciones al simulador (segunda validacion)

  • Property mode set to 100644
File size: 58.4 KB
Line 
1/*
2  Copyright (C) 2012
3  Alejandro Mujica (amujica@cenditel.gob.ve)
4  José Ruiz (jruiz@cenditel.gob.ve)
5  Julie Vera (jvera@cenditel.gob.ve)
6 
7  CENDITEL Fundación Centro Nacional de Desarrollo e Investigación en
8  Tecnologías Libres
9 
10  Este programa es software libre; Usted puede usarlo bajo los términos de la
11  licencia de software GPL versión 2.0 de la Free Software Foundation.
12 
13  Este programa se distribuye con la esperanza de que sea útil, pero SIN
14  NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o
15  ADECUACIÓN A UN PROPÓSITO PARTICULAR.
16  Consulte la licencia GPL para más detalles. Usted debe recibir una copia
17  de la GPL junto con este programa; si no, escriba a la Free Software
18  Foundation Inc. 51 Franklin Street,5 Piso, Boston, MA 02110-1301, USA.
19*/
20
21/*
22  Autor:             Alejandro J. Mujica
23  Fecha de creación: 05/06/2014
24  Este archivo contiene la definición de la clase IO_Manager.
25*/
26
27# ifndef IO_MANAGER_H
28# define IO_MANAGER_H
29
30# include <tpl_graph_indexes.H>
31
32# include <product.H>
33# include <input.H>
34# include <imported_product.H>
35# include <ip_relationship.H>
36# include <exogenous_variables.H>
37# include <queries.H>
38# include <utils.H>
39
40typedef Graph_Node<std::shared_ptr<Good>> Node;
41
42typedef Graph_Arc<IP_Relationship> Arc;
43
44typedef List_Graph <Node, Arc> Graph;
45
46/** Clase de operaciones que contiene operaciones de Entrada-Salida para
47 *  un grafo que representa redes productivas sobre archivos.
48 *
49 *  Construye un grafo de la información de base de datos a partir del archivo
50 *  xml con las raíces, añade un grafo a un archivo xml, lee un grafo de un xml,
51 *  lee los valores de simulación de un xml y añade valores de simulación a un
52 *  xml.
53 *
54 *  @author Alejandro J. Mujica
55 */
56class IO_Manager {
57
58public:
59
60  static const std::string ZERO;
61
62  static const std::string ONE;
63
64  static const std::string UTF_8;
65
66  static const std::string VALUE;
67
68  static const std::string PRODUCTION;
69
70  static const std::string ATTRIBUTES;
71
72  static const std::string YEAR;
73
74  static const std::string ROOT_NODE;
75
76  static const std::string CODE;
77
78  static const std::string RANKS;
79
80  static const std::string UP;
81
82  static const std::string DOWN;
83
84  static const std::string COPYRIGHT;
85
86  static const std::string XML_GRAPH;
87
88  static const std::string XML_NODES;
89
90  static const std::string XML_NODE;
91
92  static const std::string XML_ARCS;
93
94  static const std::string XML_ARC;
95
96  static const std::string XML_SIMULATION;
97
98  static const std::string XML_SIMULATED_GRAPH;
99
100  static const std::string XML_SIMULATED_NODES;
101
102  static const std::string XML_SIMULATED_NODE;
103
104  static const std::string XML_SIMULATED_ARCS;
105
106  static const std::string XML_SIMULATED_ARC;
107
108  static const std::string XML_SIMULATED_STATES;
109
110  static const std::string XML_SIMULATED_STATE;
111
112  static const std::string XML_STATE_NUMBER;
113
114  static const std::string XML_STOCK;
115
116  static const std::string XML_INTERNAL_REQUESTED_QUANTITY;
117
118  static const std::string XML_EXTERNAL_REQUESTED_QUANTITY;
119
120  static const std::string XML_TOTAL_REQUESTED_QUANTITY;
121
122  static const std::string XML_DAILY_WAGE;
123
124  static const std::string XML_OTHER_WAGE;
125
126  static const std::string XML_OTHER_DAILY_WAGE;
127
128  static const std::string XML_DAILY_FEEDING_COUPON;
129
130  static const std::string XML_FEEDING_COUPON;
131
132  static const std::string XML_INTEGRAL_WAGE;
133
134  static const std::string XML_ADMINISTRATIVE_STAFF_COST;
135
136  static const std::string XML_LABOR_COST;
137
138  static const std::string XML_INPUT_COST;
139
140  static const std::string XML_OTHER_COST;
141
142  static const std::string XML_TOTAL_COST;
143
144  static const std::string XML_UNITARIAN_ADMINISTRATIVE_STAFF_COST;
145
146  static const std::string XML_UNITARIAN_LABOR_COST;
147
148  static const std::string XML_INPUT_COST_PER_UNIT;
149
150  static const std::string XML_OTHER_UNITARIAN_COST;
151
152  static const std::string XML_INCOME;
153
154  static const std::string XML_ECONOMIC_STATUS;
155
156  static const std::string XML_OPTION;
157
158  static const std::string XML_VARIATION;
159
160  static const std::string XML_POSITION;
161
162  static const std::string XML_LEVEL;
163
164  static const std::string XML_COMPANY_NAME;
165
166  static const std::string XML_COMPANY_RIF;
167
168  static const std::string XML_COMPANY_LOCATION;
169
170  static const std::string XML_COMPANY_NATIONALITY;
171
172  static const std::string XML_PRODUCT_ID;
173
174  static const std::string XML_PRODUCT_NAME;
175
176  static const std::string XML_TARIFF_CODE;
177
178  static const std::string XML_MEASUREMENT_UNIT;
179
180  static const std::string XML_QUANTITY;
181
182  static const std::string XML_REQ_QUANTITY;
183
184  static const std::string XML_BOUGHT_QUANTITY;
185
186  static const std::string XML_UNITARIAN_PRICE;
187
188  static const std::string XML_TYPE;
189
190  static const std::string XML_SRC;
191
192  static const std::string XML_TGT;
193
194  static const std::string XML_INPUT_ID;
195
196  static const std::string XML_PURCHASE_PRICE;
197
198  static const std::string XML_PRODUCTION_CAPACITY;
199
200  static const std::string XML_PRODUCTION;
201
202  static const std::string XML_INTERNAL_SALES;
203
204  static const std::string XML_EXTERNAL_SALES;
205
206  static const std::string XML_WORKDAY;
207
208  static const std::string XML_NUM_ADMINISTRATIVE_STAFF;
209
210  static const std::string XML_NUM_EMPLOYEES;
211
212  static const std::string XML_PRICE;
213
214  static const std::string XML_IMPORTS;
215
216  static const std::string XML_SALE;
217
218  static const std::string XML_REQUESTED_QUANTITY;
219
220  static const std::string XML_EXOGENOUS_VARIABLES;
221
222  static const std::string XML_AVERAGE_SALARY;
223
224  static const std::string XML_RATE_OF_CHANGE_OF_SALARY;
225
226  static const std::string XML_RATE_OF_GAIN;
227
228  static const std::string XML_RATE_OF_PRICE_CHANGE;
229
230  static const std::string XML_RATE_OF_CHANGE_IN_FINAL_DEMAND;
231
232  static const std::string XML_NOMINAL_EXCHANGE_RATE;
233
234  static const std::string XML_UT;
235
236  static const std::string XML_SIGMA;
237
238  static const std::string XML_NUM_IT;
239
240  /** Busca en un árbol xml un nodo con el nombre dado
241   *
242   *  @param root puntero a la raiz del árbol.
243   *  @param name nombre del nodo que se quiere buscar.
244   *  @return Puntero al nodo con el nombre dado o NULL si no existe.
245   */
246  xmlpp::Element * search_xml_element_by_name(xmlpp::Element * root,
247                                              const std::string & name)
248  {
249    if (root->get_name() == name)
250      return root;
251
252    DynListQueue<xmlpp::Element *> queue;
253
254    queue.put(root);
255
256    while (not queue.is_empty())
257      {
258        xmlpp::Node * node = queue.get();
259
260        xmlpp::Node::NodeList children = node->get_children();
261
262        for (xmlpp::Node::NodeList::iterator it = children.begin();
263             it != children.end(); ++it)
264          {
265
266            xmlpp::Node * child = *it;
267
268            if (child->get_name() == name)
269              return static_cast <xmlpp::Element *>(child);
270
271            queue.put(static_cast <xmlpp::Element *>(child));
272          }
273      }
274
275    return NULL;
276  }
277
278  /** Lee el archivo xml y extrae el código del producto raíz.
279   *
280   *  @param[in] file_name Nombre del archivo xml.
281   *  @param[out] root_id Id del producto raíz.
282   *  @param[out] levels_upstream Cantidad máxima de niveles hacia arriba.
283   *  @param[out] levels_downstream Cantidad máxima de niveles hacia abajo.
284   *  @param[out] year Año de estudio de la red.
285   *  @throw logic_error si algún nodo no tiene atributos.
286   */
287  void read_fields(const std::string & file_name, std::string & year,
288                   db_id_t & root_id,
289                   size_t & levels_upstream, size_t & levels_downstream)
290  {
291
292    xmlpp::TextReader reader(file_name);
293
294    while(reader.read())
295      {
296        if (reader.get_name() == ROOT_NODE)
297          {
298            if (not reader.has_attributes())
299              throw std::logic_error("root has not attributes");
300
301            reader.move_to_first_attribute();
302            root_id = std::atol(reader.get_value().c_str());
303            reader.move_to_element();
304
305          }
306        else if (reader.get_name() == RANKS)
307          {
308            if (not reader.has_attributes())
309              throw std::logic_error("var ranks has not attributes");
310
311            reader.move_to_first_attribute();
312            levels_upstream = std::atol(reader.get_value().c_str());
313            reader.move_to_next_attribute();
314            levels_downstream = std::atol(reader.get_value().c_str());
315            reader.move_to_element();
316          }
317        else if (reader.get_name() == YEAR)
318          {
319            if (not reader.has_attributes())
320              throw std::logic_error("var year has not attributes");
321
322            reader.move_to_first_attribute();
323            year = reader.get_value().c_str();
324            reader.move_to_element();
325          }
326      }
327  }
328
329  /** Crea un archivo XML con los parámetros para construir una red productiva.
330   *
331   * @param year_value Año de estudio de la red productiva.
332   * @param id Id del producto que será raíz.
333   * @param levels_upstream Número máximo de niveles hacia arriba.
334   * @param levels_downstream Número máximo de niveles hacia abajo.
335   * @param output_file_name Nombre del archivo sobre el cual se escribirán
336   *        los datos.
337   */
338  void create_xml_root_file(const std::string & year_value,
339                            const db_id_t & root_id,
340                            const size_t & levels_upstream,
341                            const size_t & levels_downstream,
342                            const std::string & output_file_name)
343  {
344    xmlpp::Document doc;
345
346    xmlpp::Element * production = doc.create_root_node(PRODUCTION);
347
348    xmlpp::Element * attributes = production->add_child(ATTRIBUTES);
349
350    xmlpp::Element * year = attributes->add_child(YEAR);
351
352    year->set_attribute(VALUE, year_value);
353
354    xmlpp::Element * root = attributes->add_child(ROOT_NODE);
355
356    std::stringstream str_code;
357
358    str_code << root_id;
359
360    root->set_attribute(CODE, str_code.str());
361
362    xmlpp::Element * ranks = attributes->add_child(RANKS);
363
364    std::stringstream up_value;
365
366    up_value << levels_upstream;
367
368    ranks->set_attribute(UP, up_value.str());
369
370    std::stringstream down_value;
371
372    down_value << levels_downstream;
373
374    ranks->set_attribute(DOWN, down_value.str());
375
376    doc.write_to_file_formatted(output_file_name, UTF_8);
377  }
378
379  void set_product_info(Product * ptr_product, const std::string & year)
380  {
381    Aleph::pair<real, real> production_and_price =
382      get_produced_quantity_and_price(ptr_product->get_id(), year);
383
384    ptr_product->set_production(production_and_price.first);
385
386    ptr_product->set_price(production_and_price.second);
387
388    real used_capacity = get_product_used_capacity(ptr_product->get_id(), year);
389
390    real max_capacity = used_capacity == 0.0 ? ptr_product->get_production() :
391                        ptr_product->get_production() * 100.0 / used_capacity;
392
393    ptr_product->set_production_capacity(max_capacity);
394
395    std::tuple<real, real, real> staff_info =
396      get_product_staff_numbers(ptr_product->get_company_rif(), year,
397                                ptr_product->get_id());
398
399    ptr_product->set_workday(std::get<0>(staff_info));
400    ptr_product->set_num_administrative_staff(
401      std::ceil(std::get<1>(staff_info))
402    );
403    ptr_product->set_num_employees(std::ceil(std::get<2>(staff_info)));
404  }
405
406  /** Construye la red productiva hacia aguas arriba a partir de las raíces.
407   *
408   *  @param g Grafo sobre el cual se va a construir la red.
409   *  @param queue cola en la que se encuentran las raices para efectual el
410   *         recorrido en amplitud.
411   */
412  void build_graph_upstream(Graph & g, Graph::Node * start_node,
413                            const size_t & max_levels_upstream,
414                            const std::string & year)
415  {
416    Map<std::string, Graph::Node *> input_map;
417
418    Map<long, Graph::Node *> product_map;
419
420    Queue<Graph::Node *> queue;
421
422    queue.put(start_node);
423
424    while (not queue.is_empty())
425      {
426        Graph::Node * tgt = queue.get();
427
428        std::shared_ptr<Good> & good = tgt->get_info();
429
430        List<db_id_t> input_ids;
431
432        list_input_ids(good->get_id(), year, input_ids);
433
434        for (List<db_id_t>::Iterator iit(input_ids); iit.has_current();
435             iit.next())
436          {
437            const db_id_t & input_id = iit.get_current();
438
439            List<Input> inputs;
440
441            list_inputs(input_id, year, inputs);
442
443            for (List<Input>::Iterator it(inputs); it.has_current();
444                 it.next())
445              {
446                Input & input = it.get_current();
447
448                List<Product> products;
449
450                product_from_input(input, products);
451
452                if (products.is_empty()) // Es un insumo (nacional o importado)
453                  {
454                    Graph::Node ** ptr_src = NULL;
455                    Graph::Node *      src = NULL;
456
457                    std::stringstream scode;
458                    scode << input.get_id();
459
460                    if (input.get_nationality() != "E")
461                      scode << input.get_company_rif();
462                    else
463                      scode << input.get_company_name();
464
465                    std::string code = scode.str();
466
467                    ptr_src = input_map.search(code);
468
469                    if (ptr_src == NULL) // Hay que insertarlo en el grafo
470                      {
471                        std::shared_ptr<Good> ptr_good;
472
473                        if (input.get_nationality() != "E")
474                          ptr_good = std::shared_ptr<Good>(new Input(input));
475                        else
476                          {
477                            std::unique_ptr<Imported_Product>
478                              ptr_imported_product(new Imported_Product);
479
480                            ptr_imported_product->set_company_rif(
481                              input.get_company_rif()
482                            );
483                            ptr_imported_product->set_company_name(
484                              input.get_company_name()
485                            );
486                            ptr_imported_product->set_company_location(
487                              input.get_company_location()
488                            );
489                            ptr_imported_product->set_nationality(
490                              input.get_nationality()
491                            );
492                            ptr_imported_product->set_id(input.get_id());
493                            ptr_imported_product->set_name(input.get_name());
494                            ptr_imported_product->set_tariff_code(
495                              input.get_tariff_code()
496                            );
497                            ptr_imported_product->set_measurement_unit(
498                              input.get_measurement_unit()
499                            );
500
501                            ptr_good = std::shared_ptr<Good>(
502                                         ptr_imported_product.release()
503                                       );
504                          }
505                          src = g.insert_node(ptr_good);
506
507                          input_map.insert(code, src);
508                      }
509                    else
510                      src = *ptr_src;
511
512                    IP_Relationship ip_relationship;
513
514                    ip_relationship.set_input_id(input.get_id());
515
516                    ip_relationship.set_requested_quantity(
517                      get_unitarian_request(input.get_id(),
518                                            tgt->get_info()->get_id())
519                    );
520
521                    ip_relationship.set_purchase_price(
522                      get_acquisition_price(input.get_nationality(),
523                                            input.get_id(), year)
524                    );
525
526                    ip_relationship.set_bought_quantity(
527                      get_declared_bought_quantity(
528                        src->get_info()->get_company_rif(),
529                        src->get_info()->get_company_name(),
530                        input.get_id(),
531                        year
532                      )
533                    );
534
535                    if (input.get_nationality() != "E")
536                      {
537                        Imported_Product * ptr_imported_product =
538                          static_cast<Imported_Product *>(
539                            src->get_info().get());
540
541                        ptr_imported_product->set_imports(
542                          ptr_imported_product->get_imports() +
543                          ip_relationship.get_bought_quantity()
544                        );
545                      }
546
547                    src->get_info()->set_level(
548                      tgt->get_info()->get_level() - 1
549                    );
550
551                    g.insert_arc(src, tgt, ip_relationship);
552
553                    continue; // Paso al siguiente insumo
554                  }
555
556                  // Si llego a este punto es porque hay productos en la lista
557
558                  for (List <Product>::Iterator it(products); it.has_current();
559                       it.next())
560                    {
561                      Product & product = it.get_current();
562
563                      Graph::Node ** ptr_src = NULL;
564                      Graph::Node *      src = NULL;
565
566                      ptr_src = product_map.search(product.get_id());
567
568                      if (ptr_src == NULL)
569                        {
570                          Product * ptr_product = new Product(product);
571
572                          std::shared_ptr<Good> ptr_good(ptr_product);
573
574                          set_product_info(ptr_product, year);
575
576                          src = g.insert_node(ptr_good);
577
578                          product_map.insert(product.get_id(), src);
579                        }
580                      else
581                        src = *ptr_src;
582
583                      Product * ptr_product =
584                        static_cast<Product *>(src->get_info().get());
585
586                      IP_Relationship ip_relationship;
587
588                      ip_relationship.set_input_id(input.get_id());
589
590                      ip_relationship.set_requested_quantity(
591                        get_unitarian_request(input.get_id(),
592                                              tgt->get_info()->get_id())
593                      );
594
595                      if (ptr_product->get_price() == 0.0)
596                        get_acquisition_price(input.get_nationality(),
597                                              input.get_id(), year);
598                      else
599                        ip_relationship.set_purchase_price(
600                          ptr_product->get_price()
601                        );
602
603                      ip_relationship.set_bought_quantity(
604                        get_declared_bought_quantity(
605                          ptr_product->get_company_rif(),
606                          ptr_product->get_company_name(),
607                          input.get_id(),
608                          year
609                        )
610                      );
611
612                      src->get_info()->set_level(
613                        tgt->get_info()->get_level() - 1
614                      );
615
616                      g.insert_arc(src, tgt, ip_relationship);
617
618                      if (ptr_src == NULL and
619                          std::abs(src->get_info()->get_level()) <
620                          max_levels_upstream)
621                        queue.put(src);
622                    }
623                }
624            }
625        }
626    }
627
628    /** Construye la red productiva hacia aguas abajo a partir de las raíces.
629     *
630     *  @param g Grafo sobre el cual se va a construir la red.
631     *  @param queue cola en la que se encuentran las raices para efectual el
632     *         recorrido en amplitud.
633     */
634     void build_graph_downstream(Graph & g, Graph::Node * start_node,
635                                 const size_t & max_levels_downstream,
636                                 const std::string & year) {
637
638        Map<long, Graph::Node *> product_map;
639
640        Queue<Graph::Node *> queue;
641
642        queue.put(start_node);
643
644        while (not queue.is_empty())
645          {
646            Graph::Node * src = queue.get();
647
648            Good * good = src->get_info().get();
649
650            Product * ptr_product = static_cast<Product *>(good);
651
652            List<Aleph::pair<Product, long>> requesters;
653
654            list_requesters(good, requesters);
655
656            for (List<Aleph::pair<Product, long>>::Iterator it(requesters);
657                 it.has_current(); it.next())
658              {
659                Aleph::pair<Product, long> & current_pair = it.get_current();
660
661                Product & product = current_pair.first;
662
663                product.set_level(src->get_info()->get_level() + 1);
664
665                const db_id_t & input_id = current_pair.second;
666
667                Graph::Node ** ptr_tgt = product_map.search(product.get_id());
668
669                Graph::Node *  tgt;
670
671                if (ptr_tgt == NULL)
672                  {
673                    set_product_info(&product, year);
674                    std::shared_ptr<Good> ptr_good(new Product(product));
675                    tgt = g.insert_node(ptr_good);
676                    product_map.insert(product.get_id(), tgt);
677                  }
678                else
679                  tgt = *ptr_tgt;
680
681                IP_Relationship ip_relationship;
682
683                ip_relationship.set_input_id(input_id);
684
685                ip_relationship.set_requested_quantity(
686                  get_unitarian_request(input_id, tgt->get_info()->get_id())
687                );
688
689                ip_relationship.set_bought_quantity(
690                  get_declared_bought_quantity(
691                    ptr_product->get_company_rif(),
692                    ptr_product->get_company_name(),
693                    input_id,
694                    year
695                  )
696                );
697
698                ip_relationship.set_purchase_price(ptr_product->get_price());
699
700                g.insert_arc(src, tgt, ip_relationship);
701
702                if (tgt->get_info()->get_level() < max_levels_downstream and
703                    ptr_tgt == NULL)
704                  queue.put(tgt);
705            }
706        }
707    }
708
709  void set_internal_and_external_sales(Graph & g, const std::string & year)
710  {
711    for (Graph::Node_Iterator it(g); it.has_current(); it.next())
712      {
713
714        Graph::Node * node = it.get_current();
715
716        Good * ptr_good = node->get_info().get();
717
718        real internal_sales = 0.0;
719
720        std::string buyer_rif_set;
721
722        size_t num_buyers = 0;
723
724        real accum_price = 0.0;
725
726        for (Graph::Node_Arc_Iterator nait(node); nait.has_current();
727             nait.next())
728          {
729            Graph::Arc * arc = nait.get_current();
730
731            if (g.get_tgt_node(arc) == node)
732              continue;
733
734            const IP_Relationship & ip_rel = arc->get_info();
735
736            internal_sales += ip_rel.get_purchase_price() *
737                              ip_rel.get_bought_quantity();
738
739            Graph::Node * buyer_node = g.get_tgt_node(arc);
740
741            if (buyer_rif_set.size() > 0)
742              buyer_rif_set.append(", ");
743
744            buyer_rif_set.append(
745              single_quote(buyer_node->get_info()->get_company_rif())
746            );
747
748            accum_price += ip_rel.get_purchase_price();
749
750            ++num_buyers;
751          }
752
753        real external_sales = 0.0;
754
755        real avg_price = accum_price / num_buyers;
756
757        switch (ptr_good->get_type())
758          {
759          case PRODUCT:
760            external_sales = get_external_sales(ptr_good->get_tariff_code(),
761                                                ptr_good->get_company_rif(),
762                                                year, buyer_rif_set);
763            (static_cast<Product *>(ptr_good))
764              ->set_internal_sales(internal_sales);
765            (static_cast<Product *>(ptr_good))
766              ->set_external_sales(external_sales);
767
768            break;
769
770          case INPUT:
771            external_sales = get_external_sales(ptr_good->get_tariff_code(),
772                                                ptr_good->get_company_rif(),
773                                                year, buyer_rif_set);
774
775            (static_cast<Input *>(ptr_good))
776              ->set_internal_sales(internal_sales);
777            (static_cast<Input *>(ptr_good))
778              ->set_external_sales(external_sales);
779
780            (static_cast<Input *>(ptr_good))
781              ->set_price(avg_price);
782
783            break;
784
785          case IMPORTED_PRODUCT:
786            (static_cast<Imported_Product *>(ptr_good))
787              ->set_imports(internal_sales / avg_price);
788            (static_cast<Imported_Product *>(ptr_good))
789              ->set_sale(internal_sales);
790            (static_cast<Imported_Product *>(ptr_good))
791              ->set_requested_quantity(internal_sales / avg_price);
792            (static_cast<Imported_Product *>(ptr_good))
793              ->set_price(avg_price);
794
795          }
796      }
797  }
798
799  /** Construye el grafo a partir de los valores dados en el archivo xml.
800   *
801   *  @param file_name Nombre del archivo xml en el que se encuentra la
802   *         información relevante para la construcción de la red.
803   *  @param g Grafo sobre el cual se va a construir la red.
804   */
805  void build_graph(const std::string & file_name, Graph & g)
806  {
807    db_id_t root_id;
808
809    size_t levels_upstream;
810
811    size_t levels_downstream;
812
813    std::string year;
814
815    read_fields(file_name, year, root_id, levels_upstream, levels_downstream);
816
817    Product product = load_product_by_id(root_id);
818
819    if (product.get_id() == 0)
820      {
821        std::stringstream msg;
822        msg << "There is not product with id = " << root_id;
823        throw std::domain_error(msg.str());
824      }
825
826    set_product_info(&product, year);
827
828    std::shared_ptr<Good> ptr_good(new Product(product));
829
830    Graph::Node * r = g.insert_node(ptr_good);
831
832    if (levels_upstream > 0) 
833      build_graph_upstream(g, r, levels_upstream, year);
834
835    if (levels_downstream > 0)
836      build_graph_downstream(g, r, levels_downstream, year);
837
838    set_internal_and_external_sales(g, year);
839  }
840
841    /** Llena un arreglo de nodos que contienen espacios en blando en un árbol
842     *  xml.
843     *
844     * @param root raíz del árbol xml.
845     * @param blanks arreglo en el cual se almacenarán los nodos con espacios
846     *        en blanco.
847     */
848    void remove_white_spaces(xmlpp::Node * root,
849                             Array<xmlpp::Node *> & blanks) {
850
851        xmlpp::TextNode * node = dynamic_cast<xmlpp::TextNode *>(root);
852
853        if (node and node->is_white_space())
854            blanks.append(node);
855
856        xmlpp::Node::NodeList children = root->get_children();
857
858        for (xmlpp::Node::NodeList::iterator it = children.begin();
859             it != children.end(); ++it)
860            remove_white_spaces(*it, blanks);
861    }
862
863    /** Elimina los nodos que contienen espacios en blanco de un nodo xml.
864     *
865     * @param raíz del árbol xml.
866     */
867    void remove_white_spaces(xmlpp::Node * root) {
868
869        Array<xmlpp::Node *> blanks;
870
871        remove_white_spaces(root, blanks);
872
873        for (size_t i = 0; i < blanks.size(); ++i) {
874
875            xmlpp::Node * child = blanks.access(i);
876            xmlpp::Node * parent = child->get_parent();
877            parent->remove_child(child);
878        }
879    }
880
881  /** Añade la información de un grafo a un archivo xml.
882   *
883   * @param g grafo que se va a añadir al archivo.
884   * @param input_file_name nombre del archivo donde hay información base para
885   *        el nuevo archivo.
886   * @param output_file_name nombre del archivo en el cual se escribirá la
887   *        las información base extraída del archivo original más el grafo.
888   */
889  void add_graph_to_xml(Graph & g, const std::string & input_file_name,
890                        const std::string & output_file_name)
891  {
892    xmlpp::DomParser parser;
893
894    parser.parse_file(input_file_name);
895
896    xmlpp::Document * doc = parser.get_document();
897
898    I(doc != NULL);
899
900    xmlpp::Element * root = doc->get_root_node();
901
902    I(doc != NULL);
903
904    remove_white_spaces(root);
905
906    xmlpp::Element * graph = root->add_child(XML_GRAPH);
907
908    xmlpp::Element * nodes = graph->add_child(XML_NODES);
909
910    Map<Graph::Node *, size_t> node_map;
911
912    size_t i = 0; // Contador de nodos
913
914    for (Graph::Node_Iterator it(g); it.has_current(); it.next(), ++i)
915      {
916        Graph::Node * current_node = it.get_current();
917
918        node_map.insert(current_node, i);
919
920        Good * good = current_node->get_info().get();
921
922        xmlpp::Element * node = nodes->add_child(XML_NODE);
923
924        node->set_attribute(XML_POSITION, num_to_str(i));
925        node->set_attribute(XML_LEVEL, num_to_str(good->get_level()));
926
927        node->set_attribute(XML_COMPANY_RIF, good->get_company_rif());
928        node->set_attribute(XML_COMPANY_NAME, good->get_company_name());
929        node->set_attribute(XML_COMPANY_LOCATION, good->get_company_location());
930        node->set_attribute(XML_COMPANY_NATIONALITY, good->get_nationality());
931
932        node->set_attribute(XML_PRODUCT_ID, num_to_str(good->get_id()));
933        node->set_attribute(XML_PRODUCT_NAME, good->get_name());
934        node->set_attribute(XML_TARIFF_CODE, good->get_tariff_code());
935        node->set_attribute(XML_MEASUREMENT_UNIT,
936                            good->get_measurement_unit());
937
938        Good_Type type = good->get_type();
939
940        node->set_attribute(XML_TYPE, num_to_str(int(type)));
941
942        switch (type)
943          {
944          case PRODUCT:
945            {
946              Product * product = static_cast<Product *>(good);
947
948              node->set_attribute(XML_PRODUCTION_CAPACITY,
949                                  num_to_str(
950                                  product->get_production_capacity()));
951              node->set_attribute(XML_PRODUCTION,
952                                  num_to_str(product->get_production()));
953              node->set_attribute(XML_INTERNAL_SALES,
954                                  num_to_str(product->get_internal_sales()));
955              node->set_attribute(XML_EXTERNAL_SALES,
956                                  num_to_str(product->get_external_sales()));
957              node->set_attribute(XML_WORKDAY,
958                                  num_to_str(product->get_workday()));
959              node->set_attribute(XML_NUM_ADMINISTRATIVE_STAFF,
960                num_to_str(product->get_num_administrative_staff()));
961              node->set_attribute(XML_NUM_EMPLOYEES,
962                                  num_to_str(product->get_num_employees()));
963              node->set_attribute(XML_PRICE, num_to_str(product->get_price()));
964              node->set_attribute(XML_OTHER_COST,
965                                  num_to_str(product->get_other_cost()));
966            }
967
968            break;
969          case INPUT:
970            {
971              Input * input = static_cast<Input *>(good);
972
973              real production = (input->get_internal_sales() +
974                                 input->get_external_sales()) /
975                                 input->get_price();
976
977              node->set_attribute(XML_PRODUCTION, num_to_str(production));
978              node->set_attribute(XML_INTERNAL_SALES,
979                                  num_to_str(input->get_internal_sales()));
980              node->set_attribute(XML_EXTERNAL_SALES,
981                                  num_to_str(input->get_external_sales()));
982              node->set_attribute(XML_PRICE, num_to_str(input->get_price()));
983            }
984
985            break;
986          case IMPORTED_PRODUCT:
987            {
988              Imported_Product * imported_product =
989                static_cast<Imported_Product *>(good);
990
991              node->set_attribute(XML_IMPORTS,
992                                  num_to_str(imported_product->get_imports()));
993              node->set_attribute(XML_SALE,
994                                  num_to_str(imported_product->get_sale()));
995              node->set_attribute(XML_REQUESTED_QUANTITY,
996                                  num_to_str(
997                                  imported_product->get_requested_quantity()));
998              node->set_attribute(XML_PRICE,
999                                  num_to_str(imported_product->get_price()));
1000            }
1001          }
1002
1003      }
1004
1005    xmlpp::Element * arcs = graph->add_child(XML_ARCS);
1006
1007    for (Graph::Arc_Iterator it(g); it.has_current(); it.next())
1008      {
1009        Graph::Arc * current_arc = it.get_current();
1010
1011        xmlpp::Element * arc = arcs->add_child(XML_ARC);
1012
1013        const size_t & src = node_map.find(g.get_src_node(current_arc));
1014
1015        arc->set_attribute(XML_SRC, num_to_str(src));
1016
1017        const size_t & tgt = node_map.find(g.get_tgt_node(current_arc));
1018
1019        arc->set_attribute(XML_TGT, num_to_str(tgt));
1020
1021        IP_Relationship & ip_relationship = current_arc->get_info();
1022
1023        arc->set_attribute(XML_INPUT_ID,
1024                           num_to_str(ip_relationship.get_input_id()));
1025
1026        arc->set_attribute(XML_REQUESTED_QUANTITY,
1027                           num_to_str(ip_relationship.get_requested_quantity()));
1028
1029        arc->set_attribute(XML_PURCHASE_PRICE,
1030                           num_to_str(ip_relationship.get_purchase_price()));
1031
1032        arc->set_attribute(XML_BOUGHT_QUANTITY,
1033                           num_to_str(ip_relationship.get_bought_quantity()));
1034
1035      }
1036
1037    doc->write_to_file_formatted(output_file_name, UTF_8);
1038  }
1039
1040  /** Extrae la información de un grafo de un archivo xml.
1041   *
1042   * @param file_name nombre del archivo xml.
1043   * @param g grafo sobre el cual se va a escribir la información.
1044   */
1045  std::string read_graph_from_xml(const std::string & file_name, Graph & g)
1046  {
1047    xmlpp::DomParser parser(file_name);
1048
1049    xmlpp::Document * ptr_doc = parser.get_document();
1050
1051    xmlpp::Element * root = ptr_doc->get_root_node();
1052
1053    xmlpp::Element * node_graph = search_xml_element_by_name(root, XML_GRAPH);
1054
1055    I(node_graph != NULL);
1056
1057    xmlpp::Node::NodeList children = node_graph->get_children();
1058
1059    Array<Graph::Node *> node_array;
1060
1061    for (xmlpp::Node::NodeList::iterator it = children.begin();
1062         it != children.end(); ++it)
1063      {
1064        xmlpp::Node * curr = *it;
1065
1066        if (curr->get_name() == XML_NODES)
1067          {
1068            xmlpp::Node::NodeList nodes = curr->get_children();
1069
1070            for (xmlpp::Node::NodeList::iterator nit = nodes.begin();
1071                 nit != nodes.end(); ++nit)
1072              {
1073                xmlpp::Element * node = static_cast<xmlpp::Element *>(*nit);
1074
1075                if (node->get_name() != XML_NODE)
1076                  continue;
1077
1078                size_t position = std::atol(
1079                  node->get_attribute_value(XML_POSITION).c_str());
1080
1081                std::shared_ptr<Good> good;
1082
1083                xmlpp::Attribute * attr = node->get_attribute(XML_TYPE);
1084
1085                Good_Type type =
1086                  Good_Type(std::atoi(attr->get_value().c_str()));
1087
1088                switch (type)
1089                  {
1090                  case PRODUCT:
1091                    {
1092                      std::unique_ptr<Product> product(new Product);
1093
1094                      product->set_production_capacity(
1095                        std::atof(
1096                          node->get_attribute_value(
1097                            XML_PRODUCTION_CAPACITY
1098                          ).c_str()
1099                        )
1100                      );
1101                      product->set_production(
1102                        std::atof(
1103                          node->get_attribute_value(XML_PRODUCTION).c_str()
1104                        )
1105                      );
1106                      product->set_internal_sales(
1107                        std::atof(
1108                          node->get_attribute_value(XML_INTERNAL_SALES).c_str()
1109                        )
1110                      );
1111                      product->set_external_sales(
1112                        std::atof(
1113                          node->get_attribute_value(XML_EXTERNAL_SALES).c_str()
1114                        )
1115                      );
1116                      product->set_workday(std::atof(
1117                        node->get_attribute_value(XML_WORKDAY).c_str()
1118                      ));
1119                      product->set_num_administrative_staff(std::atof(
1120                        node->get_attribute_value(
1121                          XML_NUM_ADMINISTRATIVE_STAFF).c_str()
1122                      ));
1123                      product->set_num_employees(std::atof(
1124                        node->get_attribute_value(XML_NUM_EMPLOYEES).c_str()
1125                      ));
1126                      product->set_price(
1127                        std::atof(node->get_attribute_value(XML_PRICE).c_str())
1128                      );
1129                      product->set_other_cost(
1130                        std::atof(
1131                          node->get_attribute_value(XML_OTHER_COST).c_str()
1132                        )
1133                      );
1134
1135                      good = std::shared_ptr<Good>(product.release());
1136                    }
1137                    break;
1138                  case INPUT:
1139                    {
1140                      std::unique_ptr<Input> input(new Input);
1141
1142                      input->set_internal_sales(
1143                        std::atof(
1144                          node->get_attribute_value(XML_INTERNAL_SALES).c_str()
1145                        )
1146                      );
1147                      input->set_external_sales(
1148                        std::atof(
1149                          node->get_attribute_value(XML_EXTERNAL_SALES).c_str()
1150                        )
1151                      );
1152                      input->set_price(
1153                        std::atof(node->get_attribute_value(XML_PRICE).c_str())
1154                      );
1155
1156                      good = std::shared_ptr<Good>(input.release());
1157                    }
1158                    break;
1159                  case IMPORTED_PRODUCT:
1160                    {
1161                      std::unique_ptr<Imported_Product>
1162                        imported_product(new Imported_Product);
1163
1164                      imported_product->set_imports(
1165                        std::atof(
1166                          node->get_attribute_value(XML_IMPORTS).c_str()
1167                        )
1168                      );
1169                      imported_product->set_sale(
1170                        std::atof(
1171                          node->get_attribute_value(XML_SALE).c_str()
1172                        )
1173                      );
1174                      imported_product->set_requested_quantity(
1175                        std::atof(
1176                          node->get_attribute_value(
1177                            XML_REQUESTED_QUANTITY
1178                          ).c_str()
1179                        )
1180                      );
1181                      imported_product->set_price(
1182                        std::atof(node->get_attribute_value(XML_PRICE).c_str())
1183                      );
1184
1185                      good = std::shared_ptr<Good>(imported_product.release());
1186                    }
1187                  }
1188
1189                  good->set_company_rif(
1190                    node->get_attribute_value(XML_COMPANY_RIF)
1191                  );
1192                  good->set_company_name(
1193                    node->get_attribute_value(XML_COMPANY_NAME).c_str()
1194                  );
1195                  good->set_company_location(
1196                    node->get_attribute_value(XML_COMPANY_LOCATION).c_str()
1197                  );
1198                  good->set_nationality(
1199                    node->get_attribute_value(XML_COMPANY_NATIONALITY)
1200                  );
1201
1202                  good->set_id(std::atol(
1203                    node->get_attribute_value(XML_PRODUCT_ID).c_str())
1204                  );
1205                  good->set_name(node->get_attribute_value(XML_PRODUCT_NAME));
1206                  good->set_tariff_code(
1207                    node->get_attribute_value(XML_TARIFF_CODE)
1208                  );
1209                  good->set_measurement_unit(
1210                    node->get_attribute_value(XML_MEASUREMENT_UNIT)
1211                  );
1212                  good->set_level(
1213                    std::atoi(node->get_attribute_value(XML_LEVEL).c_str())
1214                  );
1215
1216                  node_array.touch(position) = g.insert_node(good);
1217                }
1218
1219          }
1220        else if (curr->get_name() == XML_ARCS)
1221          {
1222            xmlpp::Node::NodeList arcs = curr->get_children();
1223
1224            for (xmlpp::Node::NodeList::iterator ait = arcs.begin();
1225                 ait != arcs.end(); ++ait)
1226              {
1227                xmlpp::Element * arc = static_cast<xmlpp::Element *>(*ait);
1228
1229                if (arc->get_name() != XML_ARC)
1230                  continue;
1231
1232                size_t src =
1233                  std::atol(arc->get_attribute_value(XML_SRC).c_str());
1234
1235                size_t tgt =
1236                  std::atol(arc->get_attribute_value(XML_TGT).c_str());
1237
1238                IP_Relationship ip_relationship;
1239
1240                ip_relationship.set_input_id(
1241                  std::atol(arc->get_attribute_value(XML_INPUT_ID).c_str())
1242                );
1243
1244                ip_relationship.set_requested_quantity(
1245                  std::atof(
1246                    arc->get_attribute_value(XML_REQUESTED_QUANTITY).c_str()
1247                  )
1248                );
1249
1250                ip_relationship.set_purchase_price(
1251                  std::atof(
1252                    arc->get_attribute_value(XML_PURCHASE_PRICE).c_str()
1253                  )
1254                );
1255
1256                ip_relationship.set_bought_quantity(
1257                  std::atof(
1258                    arc->get_attribute_value(XML_BOUGHT_QUANTITY).c_str()
1259                  )
1260                );
1261
1262                Graph::Node * s = node_array.access(src);
1263
1264                Graph::Node * t = node_array.access(tgt);
1265
1266                g.insert_arc(s, t, ip_relationship);
1267              }
1268          }
1269      }
1270
1271    xmlpp::Element * year = search_xml_element_by_name(root, YEAR);
1272    I(year != NULL);
1273    return year->get_attribute_value(VALUE);
1274  }
1275
1276  struct Write_Exogenous_Variables_Simulation_Attributes
1277  {
1278    xmlpp::Element * exo_var;
1279
1280    Write_Exogenous_Variables_Simulation_Attributes(xmlpp::Element * _exo_var)
1281      : exo_var(_exo_var)
1282    {
1283      // Empty
1284    }
1285
1286    void operator () (Exogenous_Variables_Simulation_Attributes & st)
1287    {
1288      xmlpp::Element * state = exo_var->add_child(XML_SIMULATED_STATE);
1289
1290      state->set_attribute(XML_STATE_NUMBER, num_to_str(st.state_number));
1291
1292      state->set_attribute(XML_RATE_OF_CHANGE_OF_SALARY,
1293                           num_to_str(st.rate_of_change_of_salary));
1294
1295      state->set_attribute(XML_RATE_OF_GAIN, num_to_str(st.rate_of_gain));
1296
1297      state->set_attribute(XML_RATE_OF_PRICE_CHANGE,
1298                           num_to_str(st.rate_of_price_change));
1299
1300      state->set_attribute(XML_RATE_OF_CHANGE_IN_FINAL_DEMAND,
1301                           num_to_str(st.rate_of_change_in_final_demand));
1302
1303      state->set_attribute(XML_NOMINAL_EXCHANGE_RATE,
1304                           num_to_str(st.nominal_exchange_rate));
1305
1306      state->set_attribute(XML_UT, num_to_str(st.UT));
1307    }
1308  };
1309
1310  /** Escribe sobre un archivo xml los valores de la única instancia de
1311   *  variables exógenas.
1312   *
1313   * @param input_file_name nombre del archivo donde hay información base para
1314   *        el nuevo archivo.
1315   * @param output_file_name nombre del archivo en el cual se escribirá la
1316   *        las información base extraída del archivo original más las variables
1317   *        exógenas.
1318   */
1319  void add_exogenous_variables_to_xml(const std::string & input_file_name,
1320                                      const std::string & output_file_name)
1321  {
1322    xmlpp::DomParser parser;
1323
1324    parser.parse_file(input_file_name);
1325
1326    xmlpp::Document * doc = parser.get_document();
1327
1328    I(doc != NULL);
1329
1330    xmlpp::Element * root = doc->get_root_node();
1331
1332    I(doc != NULL);
1333
1334    remove_white_spaces(root);
1335
1336    Exogenous_Variables & ex_var = Exogenous_Variables::get_instance();
1337
1338    xmlpp::Element * node = root->add_child(XML_EXOGENOUS_VARIABLES);
1339
1340    node->set_attribute(XML_AVERAGE_SALARY,
1341                        num_to_str(ex_var.get_average_salary()));
1342
1343    node->set_attribute(XML_SIGMA, num_to_str(ex_var.get_sigma()));
1344
1345    node->set_attribute(XML_NUM_IT, num_to_str(ex_var.get_num_it()));
1346
1347    ex_var.for_each_simulation_attributes(
1348      Write_Exogenous_Variables_Simulation_Attributes(node)     
1349    );
1350
1351    doc->write_to_file_formatted(output_file_name, UTF_8);
1352  }
1353
1354  /** Carga sobre la única instancia de variables exógenas los valores de un
1355   *  xml.
1356   *
1357   *  @param file_name nombre del archivo xml.
1358   */
1359  void load_exogenous_variables_from_xml(const std::string & file_name)
1360  {
1361    xmlpp::DomParser parser(file_name);
1362
1363    xmlpp::Document * ptr_doc = parser.get_document();
1364
1365    xmlpp::Element * root = ptr_doc->get_root_node();
1366
1367    xmlpp::Element * node = search_xml_element_by_name(root,
1368                                                       XML_EXOGENOUS_VARIABLES);
1369
1370    I(node != NULL);
1371
1372    Exogenous_Variables & ex_var = Exogenous_Variables::get_instance();
1373
1374    ex_var.set_average_salary(
1375      std::atof(node->get_attribute_value(XML_AVERAGE_SALARY).c_str())
1376    );
1377
1378    ex_var.set_sigma(std::atof(node->get_attribute_value(XML_SIGMA).c_str()));
1379
1380    ex_var.set_num_it(std::atol(node->get_attribute_value(XML_NUM_IT).c_str()));
1381
1382    xmlpp::Node::NodeList states = node->get_children();
1383
1384    for (xmlpp::Node::NodeList::iterator it = states.begin();
1385         it != states.end(); ++it)
1386      {
1387        xmlpp::Element * state = static_cast<xmlpp::Element *>(*it);
1388
1389        if (state->get_name() != XML_SIMULATED_STATE)
1390          continue; 
1391
1392        Exogenous_Variables_Simulation_Attributes sim_attr;
1393
1394        sim_attr.state_number = std::atol(state->get_attribute_value(
1395                                          XML_STATE_NUMBER).c_str());
1396
1397        sim_attr.rate_of_change_of_salary =
1398          std::atof(state->get_attribute_value(
1399            XML_RATE_OF_CHANGE_OF_SALARY).c_str());
1400
1401        sim_attr.rate_of_gain = std::atof(state->get_attribute_value(
1402                                          XML_RATE_OF_GAIN).c_str());
1403
1404        sim_attr.rate_of_price_change =
1405          std::atof(state->get_attribute_value(
1406            XML_RATE_OF_PRICE_CHANGE).c_str());
1407
1408        sim_attr.rate_of_change_in_final_demand =
1409          std::atof(state->get_attribute_value(
1410            XML_RATE_OF_CHANGE_IN_FINAL_DEMAND).c_str());
1411
1412        sim_attr.nominal_exchange_rate =
1413          std::atof(state->get_attribute_value(
1414            XML_NOMINAL_EXCHANGE_RATE).c_str());
1415
1416        sim_attr.UT = std::atof(state->get_attribute_value(XML_UT).c_str());
1417
1418        ex_var.add_simulation_attributes(sim_attr);
1419      }
1420  }
1421
1422  struct Write_Product_Simulation_Attributes
1423  {
1424    xmlpp::Element * states;
1425
1426    Write_Product_Simulation_Attributes(xmlpp::Element * _states)
1427      : states(_states)
1428    {
1429      // Empty
1430    }
1431
1432    void operator () (Product_Simulation_Attributes & st)
1433    {
1434      xmlpp::Element * state = states->add_child(XML_SIMULATED_STATE);
1435
1436      state->set_attribute(XML_STATE_NUMBER, num_to_str(st.state_number));
1437      state->set_attribute(XML_PRODUCTION, num_to_str(st.production));
1438      state->set_attribute(XML_STOCK, num_to_str(st.stock));
1439      state->set_attribute(XML_INTERNAL_SALES, num_to_str(st.internal_sales));
1440      state->set_attribute(XML_EXTERNAL_SALES, num_to_str(st.external_sales));
1441      state->set_attribute(XML_INTERNAL_REQUESTED_QUANTITY,
1442                           num_to_str(st.internal_requested_quantity));
1443      state->set_attribute(XML_EXTERNAL_REQUESTED_QUANTITY,
1444                           num_to_str(st.external_requested_quantity));
1445      state->set_attribute(XML_NUM_EMPLOYEES, num_to_str(st.num_employees));
1446      state->set_attribute(XML_DAILY_WAGE, num_to_str(st.daily_wage));
1447      state->set_attribute(XML_OTHER_WAGE, num_to_str(st.other_wage));
1448      state->set_attribute(XML_OTHER_DAILY_WAGE,
1449                           num_to_str(st.other_daily_wage));
1450      state->set_attribute(XML_DAILY_FEEDING_COUPON,
1451                           num_to_str(st.daily_feeding_coupon));
1452      state->set_attribute(XML_FEEDING_COUPON, num_to_str(st.feeding_coupon));
1453      state->set_attribute(XML_INTEGRAL_WAGE, num_to_str(st.integral_wage));
1454      state->set_attribute(XML_ADMINISTRATIVE_STAFF_COST,
1455                           num_to_str(st.administrative_staff_cost));
1456      state->set_attribute(XML_LABOR_COST, num_to_str(st.labor_cost));
1457      state->set_attribute(XML_INPUT_COST, num_to_str(st.input_cost));
1458      state->set_attribute(XML_OTHER_COST, num_to_str(st.other_cost));
1459      state->set_attribute(XML_TOTAL_COST, num_to_str(st.total_cost));
1460      state->set_attribute(XML_UNITARIAN_ADMINISTRATIVE_STAFF_COST,
1461                           num_to_str(st.unitarian_administrative_staff_cost));
1462      state->set_attribute(XML_UNITARIAN_LABOR_COST,
1463                           num_to_str(st.unitarian_labor_cost));
1464      state->set_attribute(XML_INPUT_COST_PER_UNIT,
1465                           num_to_str(st.input_cost_per_unit));
1466      state->set_attribute(XML_OTHER_UNITARIAN_COST,
1467                           num_to_str(st.other_unitarian_cost));
1468      state->set_attribute(XML_PRICE, num_to_str(st.price));
1469      state->set_attribute(XML_INCOME, num_to_str(st.income));
1470      state->set_attribute(XML_ECONOMIC_STATUS, num_to_str(st.economic_status));
1471    }
1472  };
1473
1474  struct Write_Input_Simulation_Attributes
1475  {
1476    xmlpp::Element * states;
1477
1478    Write_Input_Simulation_Attributes(xmlpp::Element * _states)
1479      : states(_states)
1480    {
1481      // Empty
1482    }
1483
1484    void operator () (Input_Simulation_Attributes & st)
1485    {
1486      xmlpp::Element * state = states->add_child(XML_SIMULATED_STATE);
1487
1488      state->set_attribute(XML_STATE_NUMBER, num_to_str(st.state_number));
1489      state->set_attribute(XML_PRODUCTION, num_to_str(st.production));
1490      state->set_attribute(XML_STOCK, num_to_str(st.stock));
1491      state->set_attribute(XML_INTERNAL_SALES, num_to_str(st.internal_sales));
1492      state->set_attribute(XML_EXTERNAL_SALES, num_to_str(st.external_sales));
1493      state->set_attribute(XML_INTERNAL_REQUESTED_QUANTITY,
1494                           num_to_str(st.internal_requested_quantity));
1495      state->set_attribute(XML_EXTERNAL_REQUESTED_QUANTITY,
1496                           num_to_str(st.external_requested_quantity));
1497      state->set_attribute(XML_PRICE, num_to_str(st.price));
1498    }
1499  };
1500
1501  struct Write_Imported_Product_Simulation_Attributes
1502  {
1503    xmlpp::Element * states;
1504
1505    Write_Imported_Product_Simulation_Attributes(xmlpp::Element * _states)
1506      : states(_states)
1507    {
1508      // Empty
1509    }
1510
1511    void operator () (Imported_Product_Simulation_Attributes & st)
1512    {
1513      xmlpp::Element * state = states->add_child(XML_SIMULATED_STATE);
1514
1515      state->set_attribute(XML_STATE_NUMBER, num_to_str(st.state_number));
1516      state->set_attribute(XML_IMPORTS, num_to_str(st.imports));
1517      state->set_attribute(XML_STOCK, num_to_str(st.stock));
1518      state->set_attribute(XML_SALE, num_to_str(st.sales));
1519      state->set_attribute(XML_REQUESTED_QUANTITY,
1520                           num_to_str(st.requested_quantity));
1521      state->set_attribute(XML_PRICE, num_to_str(st.price));
1522    }
1523  };
1524
1525  struct Write_IP_Simulation_Attributes
1526  {
1527    xmlpp::Element * states;
1528
1529    Write_IP_Simulation_Attributes(xmlpp::Element * _states)
1530      : states(_states)
1531    {
1532      // Empty
1533    }
1534
1535    void operator () (IP_Simulation_Attributes & st)
1536    {
1537      xmlpp::Element * state = states->add_child(XML_SIMULATED_STATE);
1538
1539      state->set_attribute(XML_STATE_NUMBER, num_to_str(st.state_number));
1540      state->set_attribute(XML_PURCHASE_PRICE, num_to_str(st.purchase_price));
1541      state->set_attribute(XML_BOUGHT_QUANTITY, num_to_str(st.bought_quantity));
1542    }
1543  };
1544
1545  /** Añade la información de un grafo simulado a un archivo xml.
1546   *
1547   * @param g grafo que se va a añadir al archivo.
1548   * @param input_file_name nombre del archivo donde hay información base para
1549   *        el nuevo archivo.
1550   * @param output_file_name nombre del archivo en el cual se escribirá la
1551   *        las información base extraída del archivo original más el grafo.
1552   */
1553  void add_sim_graph_to_xml(Graph & g, const std::string & input_file_name,
1554                            const std::string & output_file_name)
1555  {
1556    xmlpp::DomParser parser;
1557
1558    parser.parse_file(input_file_name);
1559
1560    xmlpp::Document * doc = parser.get_document();
1561
1562    I(doc != NULL);
1563
1564    xmlpp::Element * root = doc->get_root_node();
1565
1566    I(doc != NULL);
1567
1568    remove_white_spaces(root);
1569
1570    xmlpp::Element * graph = root->add_child(XML_SIMULATED_GRAPH);
1571
1572    xmlpp::Element * nodes = graph->add_child(XML_SIMULATED_NODES);
1573
1574    Map<Graph::Node *, size_t> node_map;
1575
1576    size_t i = 0; // Contador de nodos
1577
1578   for (Graph::Node_Iterator it(g); it.has_current(); it.next(), ++i)
1579     {
1580        Graph::Node * current_node = it.get_current();
1581
1582        node_map.insert(current_node, i);
1583
1584        Good * good = current_node->get_info().get();
1585
1586        xmlpp::Element * node = nodes->add_child(XML_SIMULATED_NODE);
1587
1588        xmlpp::Element * states = node->add_child(XML_SIMULATED_STATES);
1589
1590        node->set_attribute(XML_POSITION, num_to_str(i));
1591        node->set_attribute(XML_LEVEL, num_to_str(good->get_level()));
1592
1593        node->set_attribute(XML_COMPANY_RIF, good->get_company_rif());
1594        node->set_attribute(XML_COMPANY_NAME, good->get_company_name());
1595        node->set_attribute(XML_COMPANY_LOCATION, good->get_company_location());
1596        node->set_attribute(XML_COMPANY_NATIONALITY, good->get_nationality());
1597
1598        node->set_attribute(XML_PRODUCT_ID, num_to_str(good->get_id()));
1599        node->set_attribute(XML_PRODUCT_NAME, good->get_name());
1600        node->set_attribute(XML_TARIFF_CODE, good->get_tariff_code());
1601        node->set_attribute(XML_MEASUREMENT_UNIT,
1602                            good->get_measurement_unit());
1603
1604        Good_Type type = good->get_type();
1605
1606        node->set_attribute(XML_TYPE, num_to_str(int(type)));
1607
1608        switch (type)
1609          {
1610          case PRODUCT:
1611            {
1612              Product * product = static_cast<Product *>(good);
1613
1614              node->set_attribute(XML_PRODUCTION_CAPACITY,
1615                                  num_to_str(
1616                                  product->get_production_capacity()));
1617              node->set_attribute(XML_PRODUCTION,
1618                                  num_to_str(product->get_production()));
1619              node->set_attribute(XML_INTERNAL_SALES,
1620                                  num_to_str(product->get_internal_sales()));
1621              node->set_attribute(XML_EXTERNAL_SALES,
1622                                  num_to_str(product->get_external_sales()));
1623              node->set_attribute(XML_WORKDAY,
1624                                  num_to_str(product->get_workday()));
1625              node->set_attribute(XML_NUM_ADMINISTRATIVE_STAFF,
1626                num_to_str(product->get_num_administrative_staff()));
1627              node->set_attribute(XML_NUM_EMPLOYEES,
1628                                  num_to_str(product->get_num_employees()));
1629              node->set_attribute(XML_PRICE, num_to_str(product->get_price()));
1630              node->set_attribute(XML_OTHER_COST,
1631                                  num_to_str(product->get_other_cost()));
1632
1633              product->for_each_simulation_attributes(
1634                Write_Product_Simulation_Attributes(states)
1635              );
1636            }
1637
1638            break;
1639          case INPUT:
1640            {
1641              Input * input = static_cast<Input *>(good);
1642
1643              node->set_attribute(XML_INTERNAL_SALES,
1644                                  num_to_str(input->get_internal_sales()));
1645              node->set_attribute(XML_EXTERNAL_SALES,
1646                                  num_to_str(input->get_external_sales()));
1647              node->set_attribute(XML_PRICE, num_to_str(input->get_price()));
1648
1649              input->for_each_simulation_attributes(
1650                Write_Input_Simulation_Attributes(states)
1651              );
1652            }
1653
1654            break;
1655          case IMPORTED_PRODUCT:
1656            {
1657              Imported_Product * imported_product =
1658                static_cast<Imported_Product *>(good);
1659
1660              node->set_attribute(XML_IMPORTS,
1661                                  num_to_str(imported_product->get_imports()));
1662              node->set_attribute(XML_SALE,
1663                                  num_to_str(imported_product->get_sale()));
1664              node->set_attribute(XML_REQUESTED_QUANTITY,
1665                                  num_to_str(
1666                                  imported_product->get_requested_quantity()));
1667              node->set_attribute(XML_PRICE,
1668                                  num_to_str(imported_product->get_price()));
1669
1670              imported_product->for_each_simulation_attributes(
1671                Write_Imported_Product_Simulation_Attributes(states)
1672              );
1673            }
1674          }
1675     }
1676
1677    xmlpp::Element * arcs = graph->add_child(XML_SIMULATED_ARCS);
1678
1679    for (Graph::Arc_Iterator it(g); it.has_current(); it.next())
1680      {
1681        Graph::Arc * current_arc = it.get_current();
1682
1683        xmlpp::Element * arc = arcs->add_child(XML_SIMULATED_ARC);
1684
1685        xmlpp::Element * states = arc->add_child(XML_SIMULATED_STATES);
1686
1687        const size_t & src = node_map.find(g.get_src_node(current_arc));
1688
1689        arc->set_attribute(XML_SRC, num_to_str(src));
1690
1691        const size_t & tgt = node_map.find(g.get_tgt_node(current_arc));
1692
1693        arc->set_attribute(XML_TGT, num_to_str(tgt));
1694
1695        IP_Relationship & ip_relationship = current_arc->get_info();
1696
1697        arc->set_attribute(XML_INPUT_ID,
1698                           num_to_str(ip_relationship.get_input_id()));
1699
1700        arc->set_attribute(XML_REQUESTED_QUANTITY,
1701                           num_to_str(ip_relationship.get_requested_quantity()));
1702
1703        arc->set_attribute(XML_PURCHASE_PRICE,
1704                           num_to_str(ip_relationship.get_purchase_price()));
1705
1706        arc->set_attribute(XML_BOUGHT_QUANTITY,
1707                           num_to_str(ip_relationship.get_bought_quantity()));
1708
1709        ip_relationship.for_each_simulation_attributes(
1710          Write_IP_Simulation_Attributes(states)
1711        );
1712      }
1713
1714    doc->write_to_file_formatted(output_file_name, UTF_8);
1715  }
1716 
1717
1718  /** Construye un archivo dot para la visualización del grafo.
1719   *
1720   * @param g grafo que se va a visualizar.
1721   * @param file_name nombre del archivo dot sobre el cual se va a escribir.
1722   */
1723  void generate_dot(Graph & g, std::ostream & output)
1724  {
1725
1726    Map <Graph::Node *, size_t> map;
1727
1728    output << "/*\n" << COPYRIGHT << "\n*/\n\n";
1729
1730    output << "/*\n"
1731           << "  Archivo generado automáticamente por generate_dot en"
1732           << " io_manager.H\n\n"
1733           << "  Autor: Alejandro J. Mujica\n"
1734           << "*/\n\n";
1735
1736    output << "digraph\n"
1737           << "{\n"
1738           << "  rankdir = LR;\n\n";   
1739
1740    size_t i = 0;
1741
1742    for (Graph::Node_Iterator it(g); it.has_current(); it.next(), ++i)
1743      {
1744        Graph::Node * p = it.get_current();
1745
1746        Good * good = p->get_info().get();
1747
1748        output << "  " << i << "[label = \"" << good->to_dot() << "\"]\n";
1749
1750        map.insert(p, i);
1751      }
1752
1753    for (Graph::Arc_Iterator it(g); it.has_current(); it.next())
1754      {
1755        Graph::Arc * a = it.get_current();
1756
1757        Graph::Node * s = g.get_src_node(a);
1758
1759        Graph::Node * t = g.get_tgt_node(a);
1760
1761        const size_t & si = map.find(s);
1762
1763        const size_t & ti = map.find(t);
1764
1765        output << "  " << si << "->" << ti
1766               << "[label = \"" << a->get_info().to_dot() << "\"];\n";
1767      }
1768
1769    output << "}";
1770  }
1771};
1772
1773# endif // IO_MANAGER_H
1774
Note: See TracBrowser for help on using the repository browser.