source: observatorio/simulacion/SimEscenariosEconomicos/simulator.C

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

Modificado para que se cree una sola conexion a la base de datos para todas las consultas en lote

  • Property mode set to 100644
File size: 36.7 KB
Line 
1/*
2  Copyright (C) 2012
3  Alejandro Mujica (amujica@cenditel.gob.ve)
4  Erwin Paredes (eparedes@cenditel.gob.ve)
5  José Ruiz (jruiz@cenditel.gob.ve)
6  Rodolfo Rangel (rrangel@cenditel.gob.ve)
7  Julie Vera (jvera@cenditel.gob.ve)
8 
9  CENDITEL Fundación Centro Nacional de Desarrollo e Investigación en
10  Tecnologías Libres
11 
12  Este programa es software libre; Usted puede usarlo bajo los términos de la
13  licencia de software GPL versión 2.0 de la Free Software Foundation.
14 
15  Este programa se distribuye con la esperanza de que sea útil, pero SIN
16  NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o
17  ADECUACIÓN A UN PROPÓSITO PARTICULAR.
18  Consulte la licencia GPL para más detalles. Usted debe recibir una copia
19  de la GPL junto con este programa; si no, escriba a la Free Software
20  Foundation Inc. 51 Franklin Street,5 Piso, Boston, MA 02110-1301, USA.
21*/
22
23# include <dbProperties.H>
24
25# include <ioManager.H>
26
27# include "internal/c.h"
28
29typedef Arcs_Index <Graph> ArcsIndex;
30
31typedef List <ProductInfo> SuggestionList;
32
33typedef Map <std::string, SuggestionList> SuggestionBuffer;
34
35/* Aquí mapeo los nodos que subieron por orden directa (es decir los que
36   aumentaron por ser nodos iniciales de estudio) con la cantidad aumentada.
37*/
38typedef Map <Graph::Node *, real> MapNodesQuantity;
39
40typedef Map <size_t, Graph::Node *> MapImports;
41
42// Mapea el id de un producto con el nodo en el grafo correspondiente
43typedef Map <long, Graph::Node *> MapProductNode;
44
45void computeOutputQuantityAndPutInQueue(Graph & g, Graph::Node * src,
46                                        DynListQueue <Graph::Node *> & q) {
47
48    real sum = 0;
49
50    for (Graph::Node_Arc_Iterator it(src); it.has_current(); it.next()) {
51
52        Graph::Arc * arc = it.get_current();
53
54        if (g.get_src_node(arc) != src)
55            continue;
56
57        sum += arc->get_info().newValue2;
58    }
59
60    for (Graph::Node_Arc_Iterator it(src); it.has_current(); it.next()) {
61
62        Graph::Arc * arc = it.get_current();
63
64        if (g.get_src_node(arc) != src)
65            continue;
66
67        const real proportion = sum == 0 ? 0 : arc->get_info().newValue2 / sum;
68
69        arc->get_info().newValue2 = src->newValue2 * proportion;
70
71        q.put(g.get_tgt_node(arc));
72    }
73}
74
75void prepareGraphForProduction(Graph & g) {
76
77    for(Graph::Node_Iterator it(g); it.has_curr() ; it.next()) {
78
79        Graph::Node * node = it.get_curr();
80
81        node->newValue1 = node->get_info()->getTotalQuantity();
82
83        node->newValue2 = node->get_info()->getQuantity();
84
85        node->newValue3 = node->get_info()->getUsedCapacity();
86    }
87
88    for(Graph::Arc_Iterator it(g); it.has_curr() ; it.next()) {
89
90        Graph::Arc * arc = it.get_curr();
91
92        arc->get_info().newValue1 = arc->get_info().totalQuantity;
93
94        arc->get_info().newValue2 = arc->get_info().quantity;
95
96        arc->get_info().newValue3 = arc->get_info().usedQuantity;
97    }
98}
99
100void computeNodeQuantity(Graph & g, Graph::Node * tgt) {
101
102    Map <long, Aleph::pair<real, real>> inputsMap;
103
104    for (Graph::Node_Arc_Iterator it(tgt); it.has_current(); it.next()) {
105
106        Graph::Arc * arc = it.get_current();
107
108        if (g.get_tgt_node(arc) != tgt)
109            continue;
110
111        Aleph::pair<real, real> * ptrPair =
112            inputsMap.search(arc->get_info().inputId);
113
114        if (ptrPair == NULL) {
115            const real & unit = arc->get_info().reqQuantity;
116
117            ptrPair =
118                inputsMap.insert(arc->get_info().inputId,
119                                 Aleph::pair<real, real>(0, unit));
120        }
121
122        ptrPair->first += arc->get_info().newValue2;
123    }
124
125    List<Aleph::pair<real, real>> list;
126
127    inputsMap.for_each(IOManager::InsertFromMapInList(list));
128
129    List <Aleph::pair<real, real>>::Iterator it(list);
130
131    Aleph::pair<real, real> & p = it.get_current();
132
133    tgt->newValue2 = p.first / p.second;
134
135    it.next();
136
137    for ( ; it.has_current(); it.next()) {
138        Aleph::pair<real, real> & _p = it.get_current();
139
140        real q = _p.first / _p.second;
141
142        if (q < tgt->newValue2)
143            tgt->newValue2 = q;
144    }
145}
146
147struct SetUsedQuantity {
148
149    Graph & g;
150
151    SetUsedQuantity(Graph & _g)
152        : g(_g) {
153
154        // Empty
155    }
156
157    void operator () (const long &, List <Graph::Arc *> & arcs) {
158
159        real sum = 0;
160
161        for (List<Graph::Arc *>::Iterator it(arcs); it.has_current(); it.next())
162            sum += it.get_current()->get_info().newValue2;
163
164        for (List<Graph::Arc *>::Iterator it(arcs); it.has_current();
165             it.next()) {
166
167            Graph::Arc * a = it.get_current();
168
169            Graph::Node * t = g.get_tgt_node(a);
170
171            real unit = a->get_info().reqQuantity;
172
173            real needed = t->newValue2 * unit;
174
175            real proportion = a->get_info().newValue2 / sum;
176
177            a->get_info().newValue3 = needed * proportion;
178
179            Graph::Node * tgt = g.get_tgt_node(a);
180
181            if ((tgt->get_info()->getTotalQuantity() >
182                tgt->get_info()->getQuantity()) and
183                (a->get_info().quantity == a->get_info().usedQuantity))
184                a->get_info().isMin = true;
185            else
186                a->get_info().isMin = false;
187        }
188    }
189};
190
191void computeUsageInputQuantities(Graph & g, Graph::Node * tgt) {
192
193    Map <long, List <Graph::Arc *>> inputsMap;
194
195    for (Graph::Node_Arc_Iterator it(tgt); it.has_current(); it.next()) {
196
197        Graph::Arc * arc = it.get_current();
198
199        if (g.get_tgt_node(arc) != tgt)
200            continue;
201
202        const long & inputId = arc->get_info().inputId;
203
204        List <Graph::Arc *> * ptrList = inputsMap.search(inputId);
205
206        if (ptrList == NULL)
207            ptrList = inputsMap.insert(inputId, List<Graph::Arc *>());
208
209        ptrList->append(arc);
210    }
211
212    inputsMap.for_each(SetUsedQuantity(g));
213}
214
215void decreaseProduction(Graph & g, Graph::Node * start, const real & value) {
216
217    start->newValue1 *= (1 - value / 100);
218
219    if (start->newValue1 >= start->newValue2)
220        return;
221
222    start->newValue2 *= (1 - value / 100);
223
224    DynListQueue <Graph::Node *> queue;
225
226    computeOutputQuantityAndPutInQueue(g, start, queue);
227
228    while (not queue.is_empty()) {
229
230        Graph::Node * p = queue.get();
231
232        computeNodeQuantity(g, p);
233        computeUsageInputQuantities(g, p);
234
235        real diff = std::fabs(p->newValue2 - p->get_info()->getQuantity());
236
237        p->newValue1 -= diff;
238
239        computeOutputQuantityAndPutInQueue(g, p, queue);
240    }
241}
242
243struct ArcsGroup {
244
245    std::string tariffCode;
246
247    real neededQuantity;
248
249    real price;
250
251    List <Graph::Arc *> arcs;
252};
253
254typedef Map <long, ArcsGroup> MapGroupArcs;
255
256void groupInputs(Graph & g, Graph::Node * tgt, MapGroupArcs & map) {
257
258    for (Graph::Node_Arc_Iterator it(tgt); it.has_current(); it.next()) {
259
260        Graph::Arc * arc = it.get_current();
261
262        if (g.get_tgt_node(arc) != tgt)
263            continue;
264
265        long inputId = arc->get_info().inputId;
266
267        ArcsGroup * ptrArcsGroup = map.search(inputId);
268
269        if (ptrArcsGroup == NULL) {
270
271            ptrArcsGroup = map.insert(inputId, ArcsGroup());
272
273            ptrArcsGroup->tariffCode =
274                g.get_src_node(arc)->get_info()->getTariffCode();
275
276            ptrArcsGroup->neededQuantity =
277                tgt->newValue2 * arc->get_info().reqQuantity;
278
279            ptrArcsGroup->price = arc->get_info().price;
280        }
281
282//        // TODO: Pendiente: Posiblemente se reste también lo que me proveen los
283//        //       proveedores no visibles en la red
284
285        ptrArcsGroup->neededQuantity -= arc->get_info().usedQuantity;
286
287        if (ptrArcsGroup->neededQuantity < 0.0)
288            ptrArcsGroup->neededQuantity = 0.0;
289
290        ptrArcsGroup->arcs.append(arc);
291    }
292}
293
294struct IncreaseUsageInArcs {
295
296    void operator () (const long &, ArcsGroup & group) {
297
298        if (group.neededQuantity <= 0)
299            return;
300
301        real sum = 0;
302
303        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
304             it.next()) {
305
306            Graph::Arc * arc = it.get_current();
307
308            ArcInfo & info = arc->get_info();
309
310            sum += info.newValue2 - info.newValue3;
311        }
312
313        real howManyIncrease = std::min(group.neededQuantity, sum);
314
315        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
316             it.next()) {
317
318            Graph::Arc * arc = it.get_current();
319
320            ArcInfo & info = arc->get_info();
321
322            real availableQuantity = info.newValue2 - info.newValue3;
323
324            real proportion = sum == 0 ? 0 : availableQuantity / sum;
325
326            real howManyIncreaseInArc = howManyIncrease * proportion;
327
328            info.newValue3 += howManyIncreaseInArc;
329
330            group.neededQuantity -= howManyIncreaseInArc;
331        }
332    }
333};
334
335struct IncreaseProductionInSuppliers {
336
337    Graph & g;
338
339    IncreaseProductionInSuppliers(Graph & _g)
340        : g(_g) {
341
342        // Empty
343    }
344
345    void operator () (const long &, ArcsGroup & group) {
346
347        if (group.neededQuantity <= 0)
348            return;
349
350        real sum = 0;
351
352        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
353             it.next()) {
354
355            Graph::Arc * arc = it.get_current();
356
357            Graph::Node * src = g.get_src_node(arc);
358
359            if (src->type == IMPORT or src->type == SUGGESTED or
360                src->get_info()->getType() == INPUT_GOOD)
361                continue;
362
363            ArcInfo & arcInfo = arc->get_info();
364
365            sum += arcInfo.newValue1 - arcInfo.newValue2;
366        }
367
368        real howManyIncrease = std::min(group.neededQuantity, sum);
369
370        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
371             it.next()) {
372
373            Graph::Arc * arc = it.get_current();
374
375            ArcInfo & arcInfo = arc->get_info();
376
377            Graph::Node * src = g.get_src_node(arc);
378
379            if (src->type == IMPORT or src->type == SUGGESTED or
380                src->get_info()->getType() == INPUT_GOOD)
381                continue;
382
383            Good * good = src->get_info().get();
384
385            real availableQuantity = arcInfo.newValue1 - arcInfo.newValue2;
386
387            real proportion = sum == 0 ? 0 : availableQuantity / sum;
388
389            real howManyIncreaseInArc = howManyIncrease * proportion;
390
391            arcInfo.newValue2 += howManyIncreaseInArc;
392            arcInfo.newValue3 += howManyIncreaseInArc;
393            group.neededQuantity -= howManyIncreaseInArc;
394
395            /* El monto de compra de la cantidad que quiero incrementar dividido
396               entre el precio unitario de venta declarado me da la cantidad
397               que debo aumentar en el nodo.
398            */
399            real nodeQuantity = howManyIncrease * arcInfo.price /
400                                good->getUnitarianPrice();
401
402            src->newValue2 += nodeQuantity;
403        }
404    }
405};
406
407struct UseNewProductionInSuppliers {
408
409    Graph & g;
410
411    MapNodesQuantity & increasedNodes;
412
413    UseNewProductionInSuppliers(Graph & _g, MapNodesQuantity & _increasedNodes)
414        : g(_g), increasedNodes(_increasedNodes) {
415
416        // Empty
417    }
418
419    void operator () (const long &, ArcsGroup & group) {
420
421        if (group.neededQuantity <= 0)
422            return;
423
424        real sum = 0;
425
426        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
427             it.next()) {
428
429            Graph::Arc * arc = it.get_current();
430
431            Graph::Node * src = g.get_src_node(arc);
432
433            real * ptrQ = increasedNodes.search(src);
434
435            if (ptrQ == NULL)
436                continue;
437
438            /*
439               Incremento cantidad disponible en nodo en función a la unidad
440               en el arco.
441            */
442            sum += *ptrQ * src->get_info()->getUnitarianPrice() /
443                   arc->get_info().price;
444        }
445
446        real howManyIncrease = std::min(group.neededQuantity, sum);
447
448        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
449             it.next()) {
450
451            Graph::Arc * arc = it.get_current();
452
453            ArcInfo & arcInfo = arc->get_info();
454
455            Graph::Node * src = g.get_src_node(arc);
456
457            real * ptrQ = increasedNodes.search(src);
458
459            if (ptrQ == NULL)
460                continue;
461
462            real q = *ptrQ * src->get_info()->getUnitarianPrice() /
463                       arc->get_info().price;
464
465            real proportion = sum == 0 ? 0 : q / sum;
466
467            real howManyIncreaseInArc = howManyIncrease * proportion;
468
469            arcInfo.newValue2 += howManyIncreaseInArc;
470            arcInfo.newValue3 += howManyIncreaseInArc;
471            group.neededQuantity -= howManyIncreaseInArc;
472
473            /*
474               Quito cantidad disponible en nodo lo que se incrementó en el
475               arco en función de la unidad en el nodo.
476            */
477            *ptrQ -= howManyIncreaseInArc * arc->get_info().price /
478                     src->get_info()->getUnitarianPrice();
479        }
480    }
481};
482
483struct IncreaseInactiveCapacity {
484
485    Graph & g;
486
487    IncreaseInactiveCapacity(Graph & _g)
488        : g(_g) {
489
490        // Empty
491    }
492
493    void operator () (const long &, ArcsGroup & group) {
494
495        if (group.neededQuantity <= 0.0)
496            return;
497
498        real sum = 0.0;
499
500        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
501             it.next()) {
502
503            Graph::Arc * arc = it.get_current();
504
505            Graph::Node * src = g.get_src_node(arc);
506
507            if (src->get_info()->getType() != PRODUCT_GOOD)
508                continue;
509
510            if (src->get_info()->getUsedCapacity() >= 100.0)
511                continue;
512
513            real totalCapacity = 100.0 * src->newValue1 / src->newValue3;
514
515            assert(arc->get_info().price > 0.0);
516
517            sum += (totalCapacity - src->newValue1) *
518                    src->get_info()->getUnitarianPrice() /
519                    arc->get_info().price;
520        }
521
522        real howManyIncrease = std::min(group.neededQuantity, sum);
523
524        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
525             it.next()) {
526
527            Graph::Arc * arc = it.get_current();
528
529            ArcInfo & arcInfo = arc->get_info();
530
531            Graph::Node * src = g.get_src_node(arc);
532
533            if (src->get_info()->getType() != PRODUCT_GOOD)
534                continue;
535
536            if (src->get_info()->getUsedCapacity() >= 100.0)
537                continue;
538
539            Good * good = src->get_info().get();
540
541            real totalCapacity = 100.0 * src->newValue1 / src->newValue3;
542
543            real q = (totalCapacity - src->newValue1) *
544                       src->get_info()->getUnitarianPrice() /
545                       arc->get_info().price;
546
547            real proportion = sum == 0.0 ? 0.0 : q / sum;
548
549            real howManyIncreaseInArc = howManyIncrease * proportion;
550
551            arcInfo.newValue1 += howManyIncreaseInArc;
552            arcInfo.newValue2 += howManyIncreaseInArc;
553            arcInfo.newValue3 += howManyIncreaseInArc;
554            group.neededQuantity -= howManyIncreaseInArc;
555
556            if (group.neededQuantity < 0.0)
557                group.neededQuantity = 0.0;
558
559            real nodeQuantity = howManyIncreaseInArc * arcInfo.price /
560                                  good->getUnitarianPrice();
561
562            src->newValue1 += nodeQuantity;
563            src->newValue2 += nodeQuantity;
564
565            src->newValue3 = 100.0 * src->newValue1 / totalCapacity;
566        }
567    }
568};
569
570struct PutSuppliersInQueue {
571
572    Graph & g;
573
574    DynListQueue <Graph::Node *> & q;
575
576    PutSuppliersInQueue(Graph & _g, DynListQueue <Graph::Node *> & _q)
577        : g(_g), q(_q) {
578
579        // Empty
580    }
581
582    void operator () (const long &, ArcsGroup & group) {
583
584        for (List<Graph::Arc *>::Iterator it(group.arcs); it.has_current();
585             it.next()) {
586
587            Graph::Arc * arc = it.get_current();
588
589            Graph::Node * src = g.get_src_node(arc);
590
591            if (src->type == IMPORT or src->type == SUGGESTED or
592                src->get_info()->getType() == INPUT_GOOD)
593                continue;
594
595            q.put(src);
596        }
597    }
598};
599
600bool eval(const long & id, List<long> & ids) {
601    for (List<long>::Iterator it(ids); it.has_current(); it.next())
602        if (id == it.get_current())
603            return false;
604    return true;
605}
606
607struct MakeSuggestions {
608
609    AutoConnection & conn;
610
611    Graph & g;
612
613    Graph::Node * tgt;
614
615    SuggestionBuffer & buffer;
616
617    const std::string & year;
618
619    MapProductNode & mapProductNode;
620
621    ArcsIndex & arcsIndex;
622
623    MakeSuggestions(AutoConnection & _conn,
624                    Graph & _g, Graph::Node * _tgt, SuggestionBuffer & _buffer,
625                    const std::string & _year, MapProductNode & _mapProductNode,
626                    ArcsIndex & _arcsIndex)
627        : conn(_conn), g(_g), tgt(_tgt), buffer(_buffer), year(_year),
628          mapProductNode(_mapProductNode), arcsIndex(_arcsIndex) {
629
630        // Empty
631    }
632
633    void operator () (const long & id, ArcsGroup & group) {
634
635        if (group.neededQuantity <= 0)
636            return;
637
638        SuggestionList * ptrSuggestions = buffer.search(group.tariffCode);
639
640        if (ptrSuggestions == NULL) {
641
642            ptrSuggestions = buffer.insert(group.tariffCode, SuggestionList());
643
644            listSuggestedSuppliers(conn, group.tariffCode, year,
645                                   *ptrSuggestions);
646        }
647
648        if (ptrSuggestions->is_empty())
649            return;
650
651        List <long> ids;
652
653        listRealProductId(conn, id, year, ids);
654
655        for (SuggestionList::Iterator it(*ptrSuggestions); it.has_current(); ){
656
657            ProductInfo & productInfo = it.get_current();
658
659            it.next();
660
661            if (not eval(productInfo.productId, ids))
662                continue;
663
664            real totalCapacity =
665                100 * productInfo.totalQuantity / productInfo.usedCapacity;
666
667            real available = totalCapacity - productInfo.totalQuantity;
668
669            if (available <= 0.0)
670                continue;
671
672            real mayIncrease =
673                available * productInfo.unitarianPrice / group.price;
674
675            real howManyIncrease = std::min(mayIncrease, group.neededQuantity);
676
677            Graph::Node * src = NULL;
678
679            Graph::Node ** ptrSrc =
680                mapProductNode.search(productInfo.productId);
681
682            if (ptrSrc == NULL) {
683
684                std::unique_ptr <Product> product(new Product);
685
686                product->setId(productInfo.productId);
687                product->setName(productInfo.name);
688                product->setTechnicalSpecifications(
689                    productInfo.technicalSpecifications);
690                product->setTariffCode(productInfo.tariffCode);
691                product->setTrademark(productInfo.trademark);
692                product->setMeasurementUnit(productInfo.measurementUnit);
693                product->setUnitarianPrice(productInfo.unitarianPrice);
694                product->setUsedCapacity(productInfo.usedCapacity);
695                product->setQuantity(productInfo.quantity);
696                product->setTotalQuantity(productInfo.totalQuantity);
697
698                Company company;
699                company.setRif(productInfo.companyRif);
700                company.setName(productInfo.companyName);
701                company.setNationality(productInfo.nationality);
702                company.setOrigCountry(productInfo.origCountry);
703                company.setProcCountry(productInfo.procCountry);
704
705                Plant plant;
706                plant.setId(productInfo.plantId);
707                plant.setName(productInfo.plantName);
708                plant.setOwnerCompany(g.searchOrInsert(company));
709
710                product->setProducerPlant(g.searchOrInsert(plant));
711
712                std::shared_ptr <Good> good(product.release());
713
714                src = g.insertNode(good);
715
716                assert(tgt->levels.size() > 0);
717
718                src->type = SUGGESTED;
719                src->id = g.get_num_nodes() - 1;
720
721                mapProductNode.insert(productInfo.productId, src);
722
723            } else
724                src = *ptrSrc;
725
726            assert(src != NULL);
727
728            real nodeQuantity = howManyIncrease * group.price /
729                                  productInfo.unitarianPrice;
730
731            productInfo.totalQuantity += nodeQuantity;
732            productInfo.quantity += nodeQuantity;
733
734            group.neededQuantity -= howManyIncrease;
735
736            productInfo.usedCapacity =
737                100 * productInfo.totalQuantity / totalCapacity;
738
739
740            src->newValue1 = productInfo.totalQuantity;
741            src->newValue2 = productInfo.quantity;
742            src->newValue3 = productInfo.usedCapacity;
743
744            tgt->levels.for_each(IOManager::SetLevelsUpstream(src));
745
746            Graph::Arc * arc = arcsIndex.search(src, tgt);
747
748            if (arc == NULL) {
749
750                ArcInfo arcInfo;
751
752                arcInfo.inputId = id;
753                arcInfo.totalQuantity = howManyIncrease;
754                arcInfo.quantity = howManyIncrease;
755                arcInfo.usedQuantity = howManyIncrease;
756
757                arc = arcsIndex.insert_in_graph(src, tgt, arcInfo);
758
759
760                arc->get_info().newValue1 = arcInfo.totalQuantity;
761                arc->get_info().newValue2 = arcInfo.quantity;
762                arc->get_info().newValue3 = arcInfo.usedQuantity;
763
764            } else {
765
766                arc->get_info().newValue1 += howManyIncrease;
767                arc->get_info().newValue2 += howManyIncrease;
768                arc->get_info().newValue3 += howManyIncrease;
769
770            }
771
772
773            if (productInfo.usedCapacity >= 100.0)
774                ptrSuggestions->remove(productInfo);
775
776            if (group.neededQuantity <= 0.0)
777                return;
778        }
779    }
780};
781
782struct SuggestImport {
783
784    AutoConnection & conn;
785
786    Graph & g;
787
788    Graph::Node * tgt;
789
790    MapImports & map;
791
792    SuggestImport(AutoConnection & _conn,
793                  Graph & _g, Graph::Node * _tgt, MapImports & _map)
794        : conn(_conn), g(_g), tgt(_tgt), map(_map) {
795
796        // Empty
797    }
798
799    void operator () (const long & id, ArcsGroup & group) {
800
801        if (group.neededQuantity <= 0)
802            return;
803
804        Graph::Node ** ptrSrc = map.search(id);
805
806        if (ptrSrc == NULL) {
807
808            std::unique_ptr <Input> input(new Input);
809
810            input->setQuantity(group.neededQuantity);
811            input->setName(getInputName(conn, id));
812
813            Company company;
814
815            company.setNationality("E");
816
817            input->setProviderCompany(g.searchOrInsert(company));
818
819            std::shared_ptr <Good> good(input.release());
820
821            Graph::Node * src = g.insertNode(good);
822
823            src->type = IMPORT;
824
825            src->newValue2 = good->getQuantity();
826
827            assert(tgt->levels.size() > 0);
828
829            tgt->levels.for_each(IOManager::SetLevelsUpstream(src));
830            src->get_info()->setMeasurementUnit(
831                tgt->get_info()->getMeasurementUnit());
832
833            ArcInfo arcInfo;
834            arcInfo.inputId = id;
835            arcInfo.totalQuantity = group.neededQuantity;
836            arcInfo.quantity = group.neededQuantity;
837            arcInfo.usedQuantity = group.neededQuantity;
838
839            g.insert_arc(src, tgt, arcInfo);
840            map.insert(id, src);
841
842       } else {
843
844            Graph::Node * src = *ptrSrc;
845
846            Graph::Node_Arc_Iterator it(src);
847
848            assert(it.has_current());
849
850            Graph::Arc * a = it.get_current();
851
852            src->get_info()->setQuantity(
853                src->get_info()->getQuantity() + group.neededQuantity);
854
855            src->newValue2 = src->get_info()->getQuantity();
856
857            ArcInfo & arcInfo = a->get_info();
858
859            arcInfo.totalQuantity += group.neededQuantity;
860            arcInfo.quantity += group.neededQuantity;
861            arcInfo.usedQuantity += group.neededQuantity;
862
863        }
864    }
865};
866
867void increaseProduction(Graph & g, Graph::Node * start, const real & value,
868                        const std::string & year, SuggestionBuffer & buffer,
869                        MapNodesQuantity & increasedNodes,
870                        MapProductNode & mapProductNode,
871                        MapImports & mapImports, ArcsIndex & arcsIndex) {
872
873    real totalCapacity = 100.0 * start->newValue1 / start->newValue3;
874
875    real toIncrease = start->newValue2 * value / 100.0;
876
877    increasedNodes.insert(start, toIncrease);
878
879    start->newValue1 += toIncrease;
880    start->newValue2 += toIncrease;
881
882    if (start->newValue1 > totalCapacity)
883        start->newValue3 = 100.0;
884    else
885        start->newValue3 = 100.0 * start->newValue1 / totalCapacity;
886
887    DynListQueue <Graph::Node *> queue;
888
889    queue.put(start);
890
891    AutoConnection conn;
892
893    while (not queue.is_empty()) {
894
895        Graph::Node * p = queue.get();
896
897        MapGroupArcs mapGroupArcs;
898
899        groupInputs(g, p, mapGroupArcs);
900
901        mapGroupArcs.for_each<IncreaseUsageInArcs>();
902
903        mapGroupArcs.for_each(IncreaseProductionInSuppliers(g));
904
905        mapGroupArcs.for_each(UseNewProductionInSuppliers(g, increasedNodes));
906
907        mapGroupArcs.for_each(IncreaseInactiveCapacity(g));
908
909        mapGroupArcs.for_each(PutSuppliersInQueue(g, queue));
910
911        mapGroupArcs.for_each(MakeSuggestions(conn, g, p, buffer, year,
912                                              mapProductNode, arcsIndex));
913
914        mapGroupArcs.for_each(SuggestImport(conn, g, p, mapImports));
915
916    }
917}
918
919
920/** Agrega un campo nuevo a cada nodo y arco del grafo tipo real para
921 * almacenar información adicional en el cálculo de variación de precios
922 *
923 * @param[in-out] g Grafo a estudiar
924 */
925void prepareGraphForCosts(Graph & g) {
926
927    for(Graph::Node_Iterator it(g); it.has_curr() ; it.next()) {
928
929        Graph::Node * node = it.get_curr();
930
931        node->newValue1 = node->get_info()->getUnitarianPrice();
932
933        node->newValue2 = 0;  //para calcular el Indice de precios
934
935    }
936
937    for(Graph::Arc_Iterator it(g); it.has_curr() ; it.next()) {
938
939        Graph::Arc * arc = it.get_curr();
940
941        Graph::Node * tgt = g.get_tgt_node(arc);
942
943        arc->get_info().newValue1 = arc->get_info().price;
944
945        // Para calcular la Proporcion del gastos en insumo
946        arc->get_info().newValue2 =
947         (arc->get_info().price / tgt->get_info()->getUnitarianPrice()) * 100;
948
949        arc->get_info().newValue3 = 0;  //Acumula el indicador de dependencia
950
951    }
952}
953
954
955/** Calcula el indicador Indices de precios Laspeyres
956 *
957 * @param[in-out] g Grafo a estudiar, Nodo de la cadena
958 */
959
960void Laspeyres(Graph & g, Graph::Node * node){
961
962    double numerator   = 0;
963
964    double denominator = 0;
965
966    for(Graph::Node_Arc_Iterator it(node); it.has_curr(); it.next()) {
967
968        Graph::Arc * arc = it.get_curr();
969
970        Graph::Node * src = g.get_src_node(arc);
971
972        if (src == node)
973            continue;
974
975        numerator += arc->get_info().newValue1 * arc->get_info().reqQuantity;
976
977        denominator += arc->get_info().price * arc->get_info().reqQuantity;
978    }
979
980    node->newValue2 = (numerator / denominator) * 100;
981
982    node->newValue2 = node->newValue2 == 0 ? 0 : node->newValue2 - 100;
983
984}
985
986
987
988/** Calcula el indicador Indices de dependencia
989 *
990 * @param[in-out] g Grafo a estudiar, Nodo de la cadena
991 */
992
993
994void dependency_indicator(Graph & g, Graph::Node * node){
995
996    double acumulator = 0;
997
998    for(Graph::Node_Arc_Iterator it(node); it.has_curr(); it.next()) {
999
1000        Graph::Arc * arc = it.get_curr();
1001
1002        Graph::Node * src = g.get_src_node(arc);
1003
1004        if (src == node)
1005            continue;
1006
1007        acumulator += arc->get_info().newValue1* arc->get_info().quantity;
1008
1009    }
1010
1011    for(Graph::Node_Arc_Iterator it(node); it.has_curr(); it.next()) {
1012
1013        Graph::Arc * arc = it.get_curr();
1014
1015        Graph::Node * src = g.get_src_node(arc);
1016
1017        if (src == node)
1018            continue;
1019
1020        real prop =  (arc->get_info().newValue1 * arc->get_info().quantity /
1021                      acumulator) * 100;
1022
1023        dependency_indicator(g, src);
1024
1025        if (COMPANY(src->get_info().get())->getNationality() != "E")
1026            node->newValue3 += (src->newValue3 / 100) * prop;
1027        else 
1028            node->newValue3 += prop;
1029    }
1030}
1031
1032void alterPriceInArcs(Graph & g, Graph::Node * node,
1033                      DynListQueue<Graph::Node *> & nodeQueue, 
1034                      const real & factor) {
1035
1036    for(Graph::Node_Arc_Iterator it(node); it.has_curr(); it.next()) {
1037
1038        Graph::Arc * arc = it.get_curr();
1039
1040        Graph::Node * tgt = g.get_tgt_node(arc);
1041
1042        if(tgt == node)
1043            continue;
1044
1045        arc->get_info().newValue1 *= factor;
1046
1047        if (not tgt->isInQueue) {
1048
1049            tgt->isInQueue = true;
1050
1051            nodeQueue.put(tgt);
1052        }
1053    }
1054}
1055
1056struct GroupPrice {
1057
1058    real reqQuantity;
1059
1060    real sumQuantity;
1061
1062    real sumQuantityOldPrice;
1063
1064    real sumQuantityNewPrice;
1065
1066    List <Graph::Arc *> arcs;
1067
1068    GroupPrice()
1069        : reqQuantity(0.0), sumQuantity(0.0), sumQuantityOldPrice(0.0),
1070          sumQuantityNewPrice(0.0) {
1071        // Empty
1072    }
1073};
1074
1075typedef Map <long, GroupPrice> MapGroupPrice;
1076
1077struct ProportionPrice {
1078
1079    const real & newUnitarianCost;
1080
1081    ProportionPrice(const real & _newUnitarianCost)
1082        : newUnitarianCost(_newUnitarianCost) {
1083
1084        // Empty
1085    }
1086
1087    void operator () (const long &, const GroupPrice & group) {
1088
1089        real proportion = (((group.sumQuantityNewPrice / group.sumQuantity) *
1090                             group.reqQuantity) / newUnitarianCost) * 100;
1091
1092        for (List <Graph::Arc *>::Iterator it(group.arcs); it.has_curr();
1093             it.next()) {
1094
1095            Graph::Arc * a = it.get_curr();
1096
1097            real prop = (a->get_info().quantity / group.sumQuantity) *
1098                         proportion;
1099
1100            it.get_current()->get_info().newValue2 = prop;
1101        }
1102    }
1103
1104};
1105
1106struct UnitarianCostSetter {
1107
1108    real & oldUnitarianCost;
1109
1110    real & newUnitarianCost;
1111
1112    UnitarianCostSetter(real & _oldUnitarianCost, real & _newUnitarianCost)
1113        : oldUnitarianCost(_oldUnitarianCost),
1114          newUnitarianCost(_newUnitarianCost) {
1115
1116        // Empty
1117    }
1118
1119    void operator () (const long &, const GroupPrice & group) {
1120
1121         oldUnitarianCost += (group.sumQuantityOldPrice / group.sumQuantity) *
1122                             group.reqQuantity;
1123
1124         newUnitarianCost += (group.sumQuantityNewPrice / group.sumQuantity) *
1125                             group.reqQuantity;
1126
1127    }
1128
1129};
1130
1131void alterPriceInNode(Graph & g, Graph::Node * node) {
1132
1133    MapGroupPrice map;
1134
1135    for(Graph::Node_Arc_Iterator it(node); it.has_curr(); it.next()) {
1136
1137        Graph::Arc * arc = it.get_curr();
1138
1139        Graph::Node * src = g.get_src_node(arc);
1140
1141        if(src == node)
1142            continue;
1143
1144        const long & inputId = arc->get_info().inputId;
1145
1146        GroupPrice * ptrGroupPrice = map.search(inputId);
1147
1148        if (ptrGroupPrice == NULL) {
1149
1150            ptrGroupPrice = map.insert(inputId, GroupPrice());
1151
1152            ptrGroupPrice->reqQuantity = arc->get_info().reqQuantity;
1153        }
1154
1155        assert(ptrGroupPrice != NULL);
1156
1157        const real & quantity = arc->get_info().quantity;
1158
1159        ptrGroupPrice->sumQuantity += quantity;
1160
1161        ptrGroupPrice->sumQuantityOldPrice += quantity *
1162                                              arc->get_info().price;
1163
1164        ptrGroupPrice->sumQuantityNewPrice += quantity *
1165                                              arc->get_info().newValue1;
1166
1167        ptrGroupPrice->arcs.append(arc);
1168
1169    }
1170
1171    real oldUnitarianCost = 0;
1172
1173    real newUnitarianCost = 0;
1174
1175    map.for_each(UnitarianCostSetter(oldUnitarianCost, newUnitarianCost));
1176
1177    map.for_each(ProportionPrice(newUnitarianCost));
1178
1179    real otherCosts = node->get_info()->getUnitarianPrice() - oldUnitarianCost;
1180
1181    node->newValue1 = newUnitarianCost + otherCosts;
1182}
1183
1184struct AlterPriceInfo {
1185
1186    Graph::Node * node;
1187
1188    real value;
1189
1190    AlterPriceInfo()
1191        : node(NULL), value(0.0) {
1192        // Empty
1193    }
1194
1195    AlterPriceInfo(Graph::Node * _node, const real & _value)
1196        : node(_node), value(_value) {
1197
1198        // Empty
1199    }
1200};
1201
1202typedef List <AlterPriceInfo> AlterPriceList;
1203
1204void alterPrice(Graph & g, AlterPriceList & list) {
1205
1206    DynListQueue<Graph::Node *> nodeQueue;
1207
1208    for (AlterPriceList::Iterator it(list); it.has_current(); it.next()) {
1209
1210        AlterPriceInfo & info = it.get_current();
1211
1212        real factor = 1 + info.value / 100;
1213
1214        info.node->newValue1 *= factor;
1215
1216        alterPriceInArcs(g, info.node, nodeQueue, factor);
1217    }
1218
1219    while (not nodeQueue.is_empty()) {
1220
1221        Graph::Node * node = nodeQueue.get();
1222
1223        node->isInQueue = false;
1224
1225        alterPriceInNode(g, node);
1226
1227        real factor = node->newValue1 /
1228                          node->get_info()->getUnitarianPrice();
1229
1230        alterPriceInArcs(g, node, nodeQueue, factor);
1231
1232        Laspeyres(g, node);
1233    }
1234}
1235
1236
1237void groupAlterListByLevels(AlterList & list,
1238                            Map <size_t, Graph::Node *> & mapNumNodes,
1239                            Array <AlterPriceList> & array) {
1240
1241    AlterList::Iterator it(list);
1242
1243    AlterInfo & alterInfo = it.get_current();
1244
1245    Graph::Node * node = mapNumNodes.find(alterInfo.numNode);
1246
1247    long minLevel = node->levels.min();
1248
1249    for ( /* nothing */; it.has_current(); it.next()) {
1250
1251        AlterInfo & alterInfo = it.get_current();
1252
1253        Graph::Node * node = mapNumNodes.find(alterInfo.numNode);
1254
1255        long level = node->levels.min();
1256
1257        if (level < minLevel)
1258            minLevel = level;
1259    }
1260
1261    it.reset_first();
1262
1263    for ( /* nothing */; it.has_current(); it.next()) {
1264
1265        AlterInfo & alterInfo = it.get_current();
1266
1267        Graph::Node * node = mapNumNodes.find(alterInfo.numNode);
1268
1269        long level = node->levels.min();
1270
1271        array.touch(level - minLevel).
1272            append(AlterPriceInfo(node, alterInfo.value));
1273    }
1274}
1275
1276int main(int argc, char const * argv[]) {
1277
1278    if (argc < 4) {
1279        std::cout << "usage: ./ecosim_simulator xmlInputFileName"
1280                  << " xmlOutputFileName"
1281                  << "  [db_server_info_file_name]\n";
1282        return 1;
1283    }
1284
1285    std::string xmlInputFileName = argv[1];
1286
1287    std::string xmlOutputFileName = argv[2];
1288
1289    std::string dbFileName = argc > 3 ? argv[3] : "dbserver";
1290
1291    DBProperties::getInstance().readFile(dbFileName);
1292
1293    IOManager ioManager;
1294
1295    Graph graph;
1296
1297    try {
1298
1299        std::string year = ioManager.readXmlGraph(xmlInputFileName,
1300                                                  IOManager::GRAPH, graph);
1301
1302        assert(graph.get_num_nodes() > 0);
1303
1304        AlterList alterList;
1305
1306        std::string option;
1307
1308        ioManager.readAlterInfo(xmlInputFileName, option, alterList);
1309
1310        if (alterList.size() == 0) {
1311
1312            std::cout << "No hay elementos para simular\n";
1313
1314            return 0;
1315        }
1316
1317        Map <size_t, Graph::Node *> mapNumNodes;
1318
1319        size_t i = 0;
1320
1321        for (Graph::Node_Iterator it(graph); it.has_current(); it.next(), ++i)
1322             mapNumNodes.insert(i, it.get_current());
1323
1324        if (option == IOManager::DECREASE) {
1325
1326            prepareGraphForProduction(graph);
1327
1328            for (AlterList::Iterator it(alterList); it.has_current();
1329                 it.next()) {
1330
1331                AlterInfo & info = it.get_current();
1332
1333                Graph::Node * node = mapNumNodes.find(info.numNode);
1334
1335                decreaseProduction(graph, node, info.value);
1336            }
1337
1338        } else if (option == IOManager::INCREASE) {
1339
1340            prepareGraphForProduction(graph);
1341
1342            SuggestionBuffer buffer;
1343
1344            MapNodesQuantity increasedNodes;
1345
1346            MapImports mapImports;
1347
1348            MapProductNode mapProductNode;
1349
1350            for (Graph::Node_Iterator it(graph); it.has_current(); it.next()) {
1351
1352                Graph::Node * currentNode = it.get_current();
1353
1354                Good * ptrGood = currentNode->get_info().get();
1355
1356                if (ptrGood->getType() == PRODUCT_GOOD)
1357                    mapProductNode.insert(ptrGood->getId(), currentNode);
1358            }
1359
1360            ArcsIndex arcsIndex(graph);
1361
1362            for (AlterList::Iterator it(alterList); it.has_current();
1363                 it.next()) {
1364
1365                AlterInfo & info = it.get_current();
1366
1367                Graph::Node * node = mapNumNodes.find(info.numNode);
1368
1369                increaseProduction(graph, node, info.value, year, buffer,
1370                                   increasedNodes, mapProductNode, mapImports,
1371                                   arcsIndex);
1372
1373            }
1374
1375        } else if (option == IOManager::COST) {
1376
1377            prepareGraphForCosts(graph);
1378
1379            Array <AlterPriceList> array;
1380
1381            groupAlterListByLevels(alterList, mapNumNodes, array);
1382
1383            for (size_t i = 0; i < array.size(); ++i)
1384                alterPrice(graph, array.access(i));
1385
1386            for (Graph::Node_Iterator it(graph); it.has_current(); it.next()) {
1387
1388                Graph::Node * currentNode = it.get_current();
1389
1390                if (currentNode->type == ROOT){
1391
1392                    dependency_indicator(graph,currentNode);
1393
1394                }
1395
1396            }
1397        }
1398
1399        ioManager.addGraphToFile(graph, xmlInputFileName, xmlOutputFileName,
1400                                 IOManager::ALTER_GRAPH);
1401
1402    } catch(const std::exception & e) {
1403
1404        std::cout << "Excepción capturada: " << e.what() << std::endl;
1405
1406        return 2;
1407    }
1408
1409    return 0;
1410}
1411
Note: See TracBrowser for help on using the repository browser.