From dc0b694edb18ff63c380b8a0d85e83ebe0a1ab87 Mon Sep 17 00:00:00 2001 From: "lucas.bruzzone" <lucasbruzzone97@gmail.com> Date: Fri, 9 Nov 2018 18:22:34 -0300 Subject: [PATCH] Add Structure of Proyect --- .../AlgoritmoGenetico/malva/.Rhistory | 0 .../AlgoritmoGenetico/malva/.cproject | 134 + .../AlgoritmoGenetico/malva/.gitignore | 6 + .../AlgoritmoGenetico/malva/.project | 79 + .../AlgoritmoGenetico/malva/Makefile | 24 + .../ProblemInstances/ATSP-instances/br17.atsp | 42 + .../ProblemInstances/ATSP-instances/ft53.atsp | 220 + .../ProblemInstances/ATSP-instances/ft70.atsp | 358 + .../ATSP-instances/ftv170.atsp | 4882 +++++++++++++ .../ATSP-instances/ftv70.atsp | 849 +++ .../ATSP-instances/rbg323.atsp | 6467 +++++++++++++++++ .../ATSP-instances/ry48p.atsp | 200 + .../ProblemInstances/DNAFA-instances/pbm.txt | 2 + .../DNAFA-instances/score.txt | 39 + .../DNAFA-instances/x60189_4.dat | 78 + .../MAXSAT-instances/format.txt | 4 + .../MAXSAT-instances/sat1.txt | 44 + .../MAXSAT-instances/sat2.txt | 4301 +++++++++++ .../MTTP-instances/mttp100.dat | 307 + .../MTTP-instances/mttp20.dat | 84 + .../ONEMAX-instances/format.txt | 1 + .../ONEMAX-instances/onemax10.txt | 1 + .../ProblemInstances/RAS-instances/RAS10.txt | 2 + .../ProblemInstances/RAS-instances/RAS20.txt | 2 + .../ProblemInstances/RAS-instances/format.txt | 2 + .../ProblemInstances/RND-instances/rnd149.txt | 1 + .../SPHERE-instances/SPH10.txt | 2 + .../SPHERE-instances/SPH20.txt | 2 + .../SPHERE-instances/format.txt | 2 + .../ProblemInstances/VRP-instances/format.txt | 3 + .../VRP-instances/vrpinfo.txt | 47 + .../ProblemInstances/VRP-instances/vrpnc1.txt | 52 + .../VRP-instances/vrpnc10.txt | 201 + .../VRP-instances/vrpnc11.txt | 122 + .../VRP-instances/vrpnc12.txt | 102 + .../VRP-instances/vrpnc13.txt | 122 + .../VRP-instances/vrpnc14.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc2.txt | 77 + .../ProblemInstances/VRP-instances/vrpnc3.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc4.txt | 152 + .../ProblemInstances/VRP-instances/vrpnc5.txt | 201 + .../ProblemInstances/VRP-instances/vrpnc6.txt | 52 + .../ProblemInstances/VRP-instances/vrpnc7.txt | 77 + .../ProblemInstances/VRP-instances/vrpnc8.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc9.txt | 152 + .../AlgoritmoGenetico/malva/README.md | 278 + .../AlgoritmoGenetico/malva/environment | 19 + .../AlgoritmoGenetico/malva/inc/Mallba | 1 + .../AlgoritmoGenetico/malva/inc/inc.env | 1 + .../AlgoritmoGenetico/malva/lib/Makefile | 8 + .../AlgoritmoGenetico/malva/lib/libmallba.a | Bin 0 -> 34998 bytes .../AlgoritmoGenetico/malva/rep/CHC/CHC.cfg | 15 + .../AlgoritmoGenetico/malva/rep/CHC/CHC.hh | 909 +++ .../malva/rep/CHC/CHC.pro.cc | 3033 ++++++++ .../AlgoritmoGenetico/malva/rep/CHC/CHC.pro.o | Bin 0 -> 191488 bytes .../malva/rep/CHC/CHC.req.cc | 332 + .../AlgoritmoGenetico/malva/rep/CHC/CHC.req.o | Bin 0 -> 25240 bytes .../malva/rep/CHC/CHCstructures.hh | 29 + .../malva/rep/CHC/Config.cfg | 3 + .../AlgoritmoGenetico/malva/rep/CHC/MainLan | Bin 0 -> 150656 bytes .../malva/rep/CHC/MainLan.cc | 49 + .../AlgoritmoGenetico/malva/rep/CHC/MainLan.o | Bin 0 -> 8992 bytes .../AlgoritmoGenetico/malva/rep/CHC/MainSeq | Bin 0 -> 150704 bytes .../malva/rep/CHC/MainSeq.cc | 43 + .../AlgoritmoGenetico/malva/rep/CHC/MainSeq.o | Bin 0 -> 8624 bytes .../malva/rep/CHC/MainWan.cc | 52 + .../AlgoritmoGenetico/malva/rep/CHC/Makefile | 24 + .../malva/rep/CHC/res/empty.txt | 0 .../AlgoritmoGenetico/malva/rep/GA/Config.cfg | 3 + .../AlgoritmoGenetico/malva/rep/GA/MainLan | Bin 0 -> 172968 bytes .../AlgoritmoGenetico/malva/rep/GA/MainLan.cc | 53 + .../AlgoritmoGenetico/malva/rep/GA/MainLan.o | Bin 0 -> 9192 bytes .../AlgoritmoGenetico/malva/rep/GA/MainSeq | Bin 0 -> 172968 bytes .../AlgoritmoGenetico/malva/rep/GA/MainSeq.cc | 41 + .../AlgoritmoGenetico/malva/rep/GA/MainSeq.o | Bin 0 -> 8632 bytes .../AlgoritmoGenetico/malva/rep/GA/Makefile | 24 + .../malva/rep/GA/asignacion_colores.csv | 10 + .../malva/rep/GA/datos_cantidad_empleados | 1 + .../malva/rep/GA/datos_cantidad_tareas | 1 + .../malva/rep/GA/datos_empleados | 4 + .../malva/rep/GA/datos_tareas | 3 + .../malva/rep/GA/ejercicio2.py | 131 + .../malva/rep/GA/generador.py | 143 + .../AlgoritmoGenetico/malva/rep/GA/newGA.cfg | 18 + .../AlgoritmoGenetico/malva/rep/GA/newGA.hh | 868 +++ .../malva/rep/GA/newGA.pro.cc | 2831 ++++++++ .../malva/rep/GA/newGA.pro.o | Bin 0 -> 176256 bytes .../malva/rep/GA/newGA.req.cc | 778 ++ .../malva/rep/GA/newGA.req.o | Bin 0 -> 65312 bytes .../malva/rep/GA/newGAstructures.hh | 60 + .../malva/rep/GA/res/datos_cantidad_empleados | 1 + .../malva/rep/GA/res/datos_cantidad_tareas | 1 + .../malva/rep/GA/res/datos_empleados | 4 + .../malva/rep/GA/res/datos_tareas | 3 + .../malva/rep/GA/res/empty.txt | 0 .../malva/rep/GA/res/sol.txt | 16 + .../AlgoritmoGenetico/malva/rep/GA/solution | 3 + .../malva/rep/GA/verificador.py | 120 + .../AlgoritmoGenetico/malva/rep/Makefile | 6 + .../AlgoritmoGenetico/malva/rep/SA/Config.cfg | 3 + .../AlgoritmoGenetico/malva/rep/SA/MainLan.cc | 53 + .../AlgoritmoGenetico/malva/rep/SA/MainSeq.cc | 42 + .../AlgoritmoGenetico/malva/rep/SA/MainWan.cc | 53 + .../AlgoritmoGenetico/malva/rep/SA/Makefile | 22 + .../AlgoritmoGenetico/malva/rep/SA/SA.cfg | 9 + .../AlgoritmoGenetico/malva/rep/SA/SA.hh | 478 ++ .../AlgoritmoGenetico/malva/rep/SA/SA.req.cc | 222 + .../malva/rep/SA/StopCondition.cc | 52 + .../malva/rep/SA/StopCondition.hh | 41 + .../malva/rep/SA/dnafa/AdjKeys.cpp | 286 + .../malva/rep/SA/dnafa/AdjKeys.h | 45 + .../malva/rep/SA/dnafa/AlignedPair.h | 39 + .../malva/rep/SA/dnafa/Config.cfg | 3 + .../malva/rep/SA/dnafa/ConsensusBuilder.cpp | 286 + .../malva/rep/SA/dnafa/ConsensusBuilder.h | 53 + .../malva/rep/SA/dnafa/ContigBuilder.cpp | 238 + .../malva/rep/SA/dnafa/ContigBuilder.h | 49 + .../malva/rep/SA/dnafa/LayoutBuilder.cpp | 423 ++ .../malva/rep/SA/dnafa/LayoutBuilder.h | 53 + .../malva/rep/SA/dnafa/MainLan.cc | 57 + .../malva/rep/SA/dnafa/MainSeq.cc | 48 + .../malva/rep/SA/dnafa/Makefile | 25 + .../malva/rep/SA/dnafa/OverlapDetector.cpp | 130 + .../malva/rep/SA/dnafa/OverlapDetector.h | 45 + .../malva/rep/SA/dnafa/SA.cfg | 9 + .../malva/rep/SA/dnafa/SA.hh | 494 ++ .../malva/rep/SA/dnafa/SA.pro.cc | 1808 +++++ .../malva/rep/SA/dnafa/SA.pro.cc1 | 1837 +++++ .../malva/rep/SA/dnafa/SA.req.cc | 437 ++ .../malva/rep/SA/dnafa/StopCondition.cc | 52 + .../malva/rep/SA/dnafa/StopCondition.hh | 41 + .../malva/rep/SA/dnafa/Util.h | 71 + .../malva/rep/SA/dnafa/list.h | 300 + .../malva/rep/SA/dnafa/pgfileLan | 3 + .../malva/rep/SA/dnafa/scp.h | 53 + .../malva/rep/SA/dnafa/sga.cpp | 256 + .../malva/rep/SA/dnafa/sga.h | 52 + .../malva/rep/SA/maxsat/Config.cfg | 3 + .../malva/rep/SA/maxsat/MainLan.cc | 53 + .../malva/rep/SA/maxsat/MainSeq.cc | 42 + .../malva/rep/SA/maxsat/Makefile | 22 + .../malva/rep/SA/maxsat/SA.cfg | 9 + .../malva/rep/SA/maxsat/SA.hh | 493 ++ .../malva/rep/SA/maxsat/SA.pro.cc | 1807 +++++ .../malva/rep/SA/maxsat/SA.req.cc | 364 + .../malva/rep/SA/maxsat/StopCondition.cc | 52 + .../malva/rep/SA/maxsat/StopCondition.hh | 41 + .../malva/rep/SA/maxsat/pgfileLan | 5 + .../malva/rep/SA/onemax/Config.cfg | 3 + .../malva/rep/SA/onemax/MainLan.cc | 53 + .../malva/rep/SA/onemax/MainSeq.cc | 42 + .../malva/rep/SA/onemax/Makefile | 22 + .../malva/rep/SA/onemax/SA.cfg | 9 + .../malva/rep/SA/onemax/SA.hh | 488 ++ .../malva/rep/SA/onemax/SA.pro.cc | 1807 +++++ .../malva/rep/SA/onemax/SA.req.cc | 286 + .../malva/rep/SA/onemax/StopCondition.cc | 52 + .../malva/rep/SA/onemax/StopCondition.hh | 41 + .../malva/rep/SA/onemax/pgfileLan | 5 + .../AlgoritmoGenetico/malva/rep/SA/pgfileLan | 1 + .../AlgoritmoGenetico/malva/rep/SA/pgfileWan | 1 + .../malva/rep/SA/rnd/Config.cfg | 3 + .../malva/rep/SA/rnd/MainLan.cc | 53 + .../malva/rep/SA/rnd/MainSeq.cc | 42 + .../malva/rep/SA/rnd/Makefile | 22 + .../AlgoritmoGenetico/malva/rep/SA/rnd/SA.cfg | 9 + .../AlgoritmoGenetico/malva/rep/SA/rnd/SA.hh | 488 ++ .../malva/rep/SA/rnd/SA.pro.cc | 1807 +++++ .../malva/rep/SA/rnd/SA.req.cc | 385 + .../malva/rep/SA/rnd/StopCondition.cc | 52 + .../malva/rep/SA/rnd/StopCondition.hh | 41 + .../malva/rep/SA/rnd/pgfileLan | 5 + .../malva/rep/SA/vrp/Config.cfg | 3 + .../malva/rep/SA/vrp/MainLan.cc | 53 + .../malva/rep/SA/vrp/MainSeq.cc | 42 + .../malva/rep/SA/vrp/Makefile | 22 + .../AlgoritmoGenetico/malva/rep/SA/vrp/SA.cfg | 9 + .../AlgoritmoGenetico/malva/rep/SA/vrp/SA.hh | 499 ++ .../malva/rep/SA/vrp/SA.pro.cc | 1807 +++++ .../malva/rep/SA/vrp/SA.req.cc | 527 ++ .../malva/rep/SA/vrp/StopCondition.cc | 52 + .../malva/rep/SA/vrp/StopCondition.hh | 41 + .../malva/rep/SA/vrp/pgfileLan | 5 + .../AlgoritmoGenetico/malva/src/Makefile | 14 + .../AlgoritmoGenetico/malva/src/Matrix.hh | 337 + .../AlgoritmoGenetico/malva/src/Messages.h | 112 + .../AlgoritmoGenetico/malva/src/Rarray.h | 145 + .../AlgoritmoGenetico/malva/src/Rlist.h | 415 ++ .../AlgoritmoGenetico/malva/src/States.cc | 228 + .../AlgoritmoGenetico/malva/src/States.hh | 64 + .../AlgoritmoGenetico/malva/src/States.o | Bin 0 -> 12968 bytes .../AlgoritmoGenetico/malva/src/mallba.hh | 26 + .../AlgoritmoGenetico/malva/src/netstream.cc | 380 + .../AlgoritmoGenetico/malva/src/netstream.hh | 161 + .../AlgoritmoGenetico/malva/src/netstream.o | Bin 0 -> 18752 bytes .../AlgoritmoGenetico/malva/src/random.hh | 50 + .../AlgoritmoGenetico/malva/src/time.hh | 43 + .../malva/stat/file_stat_aco | 12 + .../malva/stat/file_stat_pop | 13 + .../malva/stat/file_stat_pso | 12 + .../AlgoritmoGenetico/malva/stat/file_stat_sa | 13 + .../AlgoritmoGenetico/malva/uml-comun.gif | Bin 0 -> 13660 bytes ProyectoFinal/CHC/malva/.Rhistory | 0 ProyectoFinal/CHC/malva/.cproject | 134 + ProyectoFinal/CHC/malva/.gitignore | 6 + ProyectoFinal/CHC/malva/.project | 79 + ProyectoFinal/CHC/malva/Makefile | 24 + .../ProblemInstances/ATSP-instances/br17.atsp | 42 + .../ProblemInstances/ATSP-instances/ft53.atsp | 220 + .../ProblemInstances/ATSP-instances/ft70.atsp | 358 + .../ATSP-instances/ftv170.atsp | 4882 +++++++++++++ .../ATSP-instances/ftv70.atsp | 849 +++ .../ATSP-instances/rbg323.atsp | 6467 +++++++++++++++++ .../ATSP-instances/ry48p.atsp | 200 + .../ProblemInstances/DNAFA-instances/pbm.txt | 2 + .../DNAFA-instances/score.txt | 39 + .../DNAFA-instances/x60189_4.dat | 78 + .../MAXSAT-instances/format.txt | 4 + .../MAXSAT-instances/sat1.txt | 44 + .../MAXSAT-instances/sat2.txt | 4301 +++++++++++ .../MTTP-instances/mttp100.dat | 307 + .../MTTP-instances/mttp20.dat | 84 + .../ONEMAX-instances/format.txt | 1 + .../ONEMAX-instances/onemax10.txt | 1 + .../ProblemInstances/RAS-instances/RAS10.txt | 2 + .../ProblemInstances/RAS-instances/RAS20.txt | 2 + .../ProblemInstances/RAS-instances/format.txt | 2 + .../ProblemInstances/RND-instances/rnd149.txt | 1 + .../SPHERE-instances/SPH10.txt | 2 + .../SPHERE-instances/SPH20.txt | 2 + .../SPHERE-instances/format.txt | 2 + .../ProblemInstances/VRP-instances/format.txt | 3 + .../VRP-instances/vrpinfo.txt | 47 + .../ProblemInstances/VRP-instances/vrpnc1.txt | 52 + .../VRP-instances/vrpnc10.txt | 201 + .../VRP-instances/vrpnc11.txt | 122 + .../VRP-instances/vrpnc12.txt | 102 + .../VRP-instances/vrpnc13.txt | 122 + .../VRP-instances/vrpnc14.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc2.txt | 77 + .../ProblemInstances/VRP-instances/vrpnc3.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc4.txt | 152 + .../ProblemInstances/VRP-instances/vrpnc5.txt | 201 + .../ProblemInstances/VRP-instances/vrpnc6.txt | 52 + .../ProblemInstances/VRP-instances/vrpnc7.txt | 77 + .../ProblemInstances/VRP-instances/vrpnc8.txt | 102 + .../ProblemInstances/VRP-instances/vrpnc9.txt | 152 + ProyectoFinal/CHC/malva/README.md | 278 + ProyectoFinal/CHC/malva/environment | 19 + ProyectoFinal/CHC/malva/inc/Mallba | 1 + ProyectoFinal/CHC/malva/inc/inc.env | 1 + ProyectoFinal/CHC/malva/lib/Makefile | 8 + ProyectoFinal/CHC/malva/lib/libmallba.a | Bin 0 -> 34998 bytes ProyectoFinal/CHC/malva/rep/CHC/CHC.cfg | 15 + ProyectoFinal/CHC/malva/rep/CHC/CHC.hh | 909 +++ ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.cc | 3033 ++++++++ ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.o | Bin 0 -> 191488 bytes ProyectoFinal/CHC/malva/rep/CHC/CHC.req.cc | 332 + ProyectoFinal/CHC/malva/rep/CHC/CHC.req.o | Bin 0 -> 25240 bytes .../CHC/malva/rep/CHC/CHCstructures.hh | 29 + ProyectoFinal/CHC/malva/rep/CHC/Config.cfg | 3 + ProyectoFinal/CHC/malva/rep/CHC/MainLan | Bin 0 -> 150656 bytes ProyectoFinal/CHC/malva/rep/CHC/MainLan.cc | 49 + ProyectoFinal/CHC/malva/rep/CHC/MainLan.o | Bin 0 -> 8992 bytes ProyectoFinal/CHC/malva/rep/CHC/MainSeq | Bin 0 -> 150704 bytes ProyectoFinal/CHC/malva/rep/CHC/MainSeq.cc | 43 + ProyectoFinal/CHC/malva/rep/CHC/MainSeq.o | Bin 0 -> 8624 bytes ProyectoFinal/CHC/malva/rep/CHC/MainWan.cc | 52 + ProyectoFinal/CHC/malva/rep/CHC/Makefile | 24 + ProyectoFinal/CHC/malva/rep/CHC/res/empty.txt | 0 ProyectoFinal/CHC/malva/rep/GA/Config.cfg | 3 + ProyectoFinal/CHC/malva/rep/GA/MainLan | Bin 0 -> 172968 bytes ProyectoFinal/CHC/malva/rep/GA/MainLan.cc | 53 + ProyectoFinal/CHC/malva/rep/GA/MainLan.o | Bin 0 -> 9192 bytes ProyectoFinal/CHC/malva/rep/GA/MainSeq | Bin 0 -> 172968 bytes ProyectoFinal/CHC/malva/rep/GA/MainSeq.cc | 41 + ProyectoFinal/CHC/malva/rep/GA/MainSeq.o | Bin 0 -> 8632 bytes ProyectoFinal/CHC/malva/rep/GA/Makefile | 24 + .../CHC/malva/rep/GA/asignacion_colores.csv | 10 + .../CHC/malva/rep/GA/datos_cantidad_empleados | 1 + .../CHC/malva/rep/GA/datos_cantidad_tareas | 1 + .../CHC/malva/rep/GA/datos_empleados | 4 + ProyectoFinal/CHC/malva/rep/GA/datos_tareas | 3 + ProyectoFinal/CHC/malva/rep/GA/ejercicio2.py | 131 + ProyectoFinal/CHC/malva/rep/GA/generador.py | 143 + ProyectoFinal/CHC/malva/rep/GA/newGA.cfg | 18 + ProyectoFinal/CHC/malva/rep/GA/newGA.hh | 868 +++ ProyectoFinal/CHC/malva/rep/GA/newGA.pro.cc | 2831 ++++++++ ProyectoFinal/CHC/malva/rep/GA/newGA.pro.o | Bin 0 -> 176256 bytes ProyectoFinal/CHC/malva/rep/GA/newGA.req.cc | 778 ++ ProyectoFinal/CHC/malva/rep/GA/newGA.req.o | Bin 0 -> 65312 bytes .../CHC/malva/rep/GA/newGAstructures.hh | 60 + .../malva/rep/GA/res/datos_cantidad_empleados | 1 + .../malva/rep/GA/res/datos_cantidad_tareas | 1 + .../CHC/malva/rep/GA/res/datos_empleados | 4 + .../CHC/malva/rep/GA/res/datos_tareas | 3 + ProyectoFinal/CHC/malva/rep/GA/res/empty.txt | 0 ProyectoFinal/CHC/malva/rep/GA/res/sol.txt | 16 + ProyectoFinal/CHC/malva/rep/GA/solution | 3 + ProyectoFinal/CHC/malva/rep/GA/verificador.py | 120 + ProyectoFinal/CHC/malva/rep/Makefile | 6 + ProyectoFinal/CHC/malva/rep/SA/Config.cfg | 3 + ProyectoFinal/CHC/malva/rep/SA/MainLan.cc | 53 + ProyectoFinal/CHC/malva/rep/SA/MainSeq.cc | 42 + ProyectoFinal/CHC/malva/rep/SA/MainWan.cc | 53 + ProyectoFinal/CHC/malva/rep/SA/Makefile | 22 + ProyectoFinal/CHC/malva/rep/SA/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/SA.hh | 478 ++ ProyectoFinal/CHC/malva/rep/SA/SA.req.cc | 222 + .../CHC/malva/rep/SA/StopCondition.cc | 52 + .../CHC/malva/rep/SA/StopCondition.hh | 41 + .../CHC/malva/rep/SA/dnafa/AdjKeys.cpp | 286 + .../CHC/malva/rep/SA/dnafa/AdjKeys.h | 45 + .../CHC/malva/rep/SA/dnafa/AlignedPair.h | 39 + .../CHC/malva/rep/SA/dnafa/Config.cfg | 3 + .../malva/rep/SA/dnafa/ConsensusBuilder.cpp | 286 + .../CHC/malva/rep/SA/dnafa/ConsensusBuilder.h | 53 + .../CHC/malva/rep/SA/dnafa/ContigBuilder.cpp | 238 + .../CHC/malva/rep/SA/dnafa/ContigBuilder.h | 49 + .../CHC/malva/rep/SA/dnafa/LayoutBuilder.cpp | 423 ++ .../CHC/malva/rep/SA/dnafa/LayoutBuilder.h | 53 + .../CHC/malva/rep/SA/dnafa/MainLan.cc | 57 + .../CHC/malva/rep/SA/dnafa/MainSeq.cc | 48 + ProyectoFinal/CHC/malva/rep/SA/dnafa/Makefile | 25 + .../malva/rep/SA/dnafa/OverlapDetector.cpp | 130 + .../CHC/malva/rep/SA/dnafa/OverlapDetector.h | 45 + ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.hh | 494 ++ .../CHC/malva/rep/SA/dnafa/SA.pro.cc | 1808 +++++ .../CHC/malva/rep/SA/dnafa/SA.pro.cc1 | 1837 +++++ .../CHC/malva/rep/SA/dnafa/SA.req.cc | 437 ++ .../CHC/malva/rep/SA/dnafa/StopCondition.cc | 52 + .../CHC/malva/rep/SA/dnafa/StopCondition.hh | 41 + ProyectoFinal/CHC/malva/rep/SA/dnafa/Util.h | 71 + ProyectoFinal/CHC/malva/rep/SA/dnafa/list.h | 300 + .../CHC/malva/rep/SA/dnafa/pgfileLan | 3 + ProyectoFinal/CHC/malva/rep/SA/dnafa/scp.h | 53 + ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.cpp | 256 + ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.h | 52 + .../CHC/malva/rep/SA/maxsat/Config.cfg | 3 + .../CHC/malva/rep/SA/maxsat/MainLan.cc | 53 + .../CHC/malva/rep/SA/maxsat/MainSeq.cc | 42 + .../CHC/malva/rep/SA/maxsat/Makefile | 22 + ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.hh | 493 ++ .../CHC/malva/rep/SA/maxsat/SA.pro.cc | 1807 +++++ .../CHC/malva/rep/SA/maxsat/SA.req.cc | 364 + .../CHC/malva/rep/SA/maxsat/StopCondition.cc | 52 + .../CHC/malva/rep/SA/maxsat/StopCondition.hh | 41 + .../CHC/malva/rep/SA/maxsat/pgfileLan | 5 + .../CHC/malva/rep/SA/onemax/Config.cfg | 3 + .../CHC/malva/rep/SA/onemax/MainLan.cc | 53 + .../CHC/malva/rep/SA/onemax/MainSeq.cc | 42 + .../CHC/malva/rep/SA/onemax/Makefile | 22 + ProyectoFinal/CHC/malva/rep/SA/onemax/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/onemax/SA.hh | 488 ++ .../CHC/malva/rep/SA/onemax/SA.pro.cc | 1807 +++++ .../CHC/malva/rep/SA/onemax/SA.req.cc | 286 + .../CHC/malva/rep/SA/onemax/StopCondition.cc | 52 + .../CHC/malva/rep/SA/onemax/StopCondition.hh | 41 + .../CHC/malva/rep/SA/onemax/pgfileLan | 5 + ProyectoFinal/CHC/malva/rep/SA/pgfileLan | 1 + ProyectoFinal/CHC/malva/rep/SA/pgfileWan | 1 + ProyectoFinal/CHC/malva/rep/SA/rnd/Config.cfg | 3 + ProyectoFinal/CHC/malva/rep/SA/rnd/MainLan.cc | 53 + ProyectoFinal/CHC/malva/rep/SA/rnd/MainSeq.cc | 42 + ProyectoFinal/CHC/malva/rep/SA/rnd/Makefile | 22 + ProyectoFinal/CHC/malva/rep/SA/rnd/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/rnd/SA.hh | 488 ++ ProyectoFinal/CHC/malva/rep/SA/rnd/SA.pro.cc | 1807 +++++ ProyectoFinal/CHC/malva/rep/SA/rnd/SA.req.cc | 385 + .../CHC/malva/rep/SA/rnd/StopCondition.cc | 52 + .../CHC/malva/rep/SA/rnd/StopCondition.hh | 41 + ProyectoFinal/CHC/malva/rep/SA/rnd/pgfileLan | 5 + ProyectoFinal/CHC/malva/rep/SA/vrp/Config.cfg | 3 + ProyectoFinal/CHC/malva/rep/SA/vrp/MainLan.cc | 53 + ProyectoFinal/CHC/malva/rep/SA/vrp/MainSeq.cc | 42 + ProyectoFinal/CHC/malva/rep/SA/vrp/Makefile | 22 + ProyectoFinal/CHC/malva/rep/SA/vrp/SA.cfg | 9 + ProyectoFinal/CHC/malva/rep/SA/vrp/SA.hh | 499 ++ ProyectoFinal/CHC/malva/rep/SA/vrp/SA.pro.cc | 1807 +++++ ProyectoFinal/CHC/malva/rep/SA/vrp/SA.req.cc | 527 ++ .../CHC/malva/rep/SA/vrp/StopCondition.cc | 52 + .../CHC/malva/rep/SA/vrp/StopCondition.hh | 41 + ProyectoFinal/CHC/malva/rep/SA/vrp/pgfileLan | 5 + ProyectoFinal/CHC/malva/src/Makefile | 14 + ProyectoFinal/CHC/malva/src/Matrix.hh | 337 + ProyectoFinal/CHC/malva/src/Messages.h | 112 + ProyectoFinal/CHC/malva/src/Rarray.h | 145 + ProyectoFinal/CHC/malva/src/Rlist.h | 415 ++ ProyectoFinal/CHC/malva/src/States.cc | 228 + ProyectoFinal/CHC/malva/src/States.hh | 64 + ProyectoFinal/CHC/malva/src/States.o | Bin 0 -> 12968 bytes ProyectoFinal/CHC/malva/src/mallba.hh | 26 + ProyectoFinal/CHC/malva/src/netstream.cc | 380 + ProyectoFinal/CHC/malva/src/netstream.hh | 161 + ProyectoFinal/CHC/malva/src/netstream.o | Bin 0 -> 18752 bytes ProyectoFinal/CHC/malva/src/random.hh | 50 + ProyectoFinal/CHC/malva/src/time.hh | 43 + ProyectoFinal/CHC/malva/stat/file_stat_aco | 12 + ProyectoFinal/CHC/malva/stat/file_stat_pop | 13 + ProyectoFinal/CHC/malva/stat/file_stat_pso | 12 + ProyectoFinal/CHC/malva/stat/file_stat_sa | 13 + ProyectoFinal/CHC/malva/uml-comun.gif | Bin 0 -> 13660 bytes 404 files changed, 103162 insertions(+) create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/.Rhistory create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/.cproject create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/.gitignore create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/.project create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/br17.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft53.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft70.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv170.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv70.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/rbg323.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ry48p.atsp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/pbm.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/score.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/x60189_4.dat create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/format.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat1.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat2.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp100.dat create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp20.dat create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/format.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/onemax10.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS10.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS20.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/format.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RND-instances/rnd149.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH10.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH20.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/format.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/format.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpinfo.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc1.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc10.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc11.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc12.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc13.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc14.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc2.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc3.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc4.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc5.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc6.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc7.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc8.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc9.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/README.md create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/environment create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/inc/Mallba create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/inc/inc.env create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/lib/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/lib/libmallba.a create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHCstructures.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainWan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/res/empty.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/asignacion_colores.csv create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_empleados create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_tareas create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_empleados create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_tareas create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/ejercicio2.py create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/generador.py create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGAstructures.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_empleados create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_tareas create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_empleados create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_tareas create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/empty.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/sol.txt create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/solution create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/verificador.py create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainWan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AlignedPair.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc1 create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Util.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/list.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/scp.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.cpp create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileWan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Config.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainLan.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainSeq.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.cfg create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.pro.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.req.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/pgfileLan create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/Makefile create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/Matrix.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/Messages.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/Rarray.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/Rlist.h create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/States.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/States.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/States.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/mallba.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.cc create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.o create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/random.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/src/time.hh create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_aco create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pop create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pso create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_sa create mode 100644 ProyectoFinal/AlgoritmoGenetico/malva/uml-comun.gif create mode 100644 ProyectoFinal/CHC/malva/.Rhistory create mode 100644 ProyectoFinal/CHC/malva/.cproject create mode 100644 ProyectoFinal/CHC/malva/.gitignore create mode 100644 ProyectoFinal/CHC/malva/.project create mode 100644 ProyectoFinal/CHC/malva/Makefile create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/br17.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft53.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft70.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv170.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv70.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/rbg323.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ry48p.atsp create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/pbm.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/score.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/x60189_4.dat create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/format.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat1.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat2.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp100.dat create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp20.dat create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/format.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/onemax10.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS10.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS20.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/format.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/RND-instances/rnd149.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH10.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH20.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/format.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/format.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpinfo.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc1.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc10.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc11.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc12.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc13.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc14.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc2.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc3.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc4.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc5.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc6.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc7.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc8.txt create mode 100644 ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc9.txt create mode 100644 ProyectoFinal/CHC/malva/README.md create mode 100644 ProyectoFinal/CHC/malva/environment create mode 100644 ProyectoFinal/CHC/malva/inc/Mallba create mode 100644 ProyectoFinal/CHC/malva/inc/inc.env create mode 100644 ProyectoFinal/CHC/malva/lib/Makefile create mode 100644 ProyectoFinal/CHC/malva/lib/libmallba.a create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.hh create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.o create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHC.req.o create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/CHCstructures.hh create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainLan create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainLan.o create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainSeq create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainSeq.o create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/MainWan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/CHC/res/empty.txt create mode 100644 ProyectoFinal/CHC/malva/rep/GA/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainLan create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainLan.o create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainSeq create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/GA/MainSeq.o create mode 100644 ProyectoFinal/CHC/malva/rep/GA/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/GA/asignacion_colores.csv create mode 100644 ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_empleados create mode 100644 ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_tareas create mode 100644 ProyectoFinal/CHC/malva/rep/GA/datos_empleados create mode 100644 ProyectoFinal/CHC/malva/rep/GA/datos_tareas create mode 100644 ProyectoFinal/CHC/malva/rep/GA/ejercicio2.py create mode 100644 ProyectoFinal/CHC/malva/rep/GA/generador.py create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.pro.o create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGA.req.o create mode 100644 ProyectoFinal/CHC/malva/rep/GA/newGAstructures.hh create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_empleados create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_tareas create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/datos_empleados create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/datos_tareas create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/empty.txt create mode 100644 ProyectoFinal/CHC/malva/rep/GA/res/sol.txt create mode 100644 ProyectoFinal/CHC/malva/rep/GA/solution create mode 100644 ProyectoFinal/CHC/malva/rep/GA/verificador.py create mode 100644 ProyectoFinal/CHC/malva/rep/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/MainWan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/AlignedPair.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc1 create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/Util.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/list.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/scp.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.cpp create mode 100644 ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.h create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/maxsat/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/SA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/onemax/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/pgfileWan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/SA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/rnd/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/Config.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/MainLan.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/MainSeq.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/Makefile create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/SA.cfg create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/SA.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/SA.pro.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/SA.req.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.cc create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.hh create mode 100644 ProyectoFinal/CHC/malva/rep/SA/vrp/pgfileLan create mode 100644 ProyectoFinal/CHC/malva/src/Makefile create mode 100644 ProyectoFinal/CHC/malva/src/Matrix.hh create mode 100644 ProyectoFinal/CHC/malva/src/Messages.h create mode 100644 ProyectoFinal/CHC/malva/src/Rarray.h create mode 100644 ProyectoFinal/CHC/malva/src/Rlist.h create mode 100644 ProyectoFinal/CHC/malva/src/States.cc create mode 100644 ProyectoFinal/CHC/malva/src/States.hh create mode 100644 ProyectoFinal/CHC/malva/src/States.o create mode 100644 ProyectoFinal/CHC/malva/src/mallba.hh create mode 100644 ProyectoFinal/CHC/malva/src/netstream.cc create mode 100644 ProyectoFinal/CHC/malva/src/netstream.hh create mode 100644 ProyectoFinal/CHC/malva/src/netstream.o create mode 100644 ProyectoFinal/CHC/malva/src/random.hh create mode 100644 ProyectoFinal/CHC/malva/src/time.hh create mode 100644 ProyectoFinal/CHC/malva/stat/file_stat_aco create mode 100644 ProyectoFinal/CHC/malva/stat/file_stat_pop create mode 100644 ProyectoFinal/CHC/malva/stat/file_stat_pso create mode 100644 ProyectoFinal/CHC/malva/stat/file_stat_sa create mode 100644 ProyectoFinal/CHC/malva/uml-comun.gif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/.Rhistory b/ProyectoFinal/AlgoritmoGenetico/malva/.Rhistory new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/.cproject b/ProyectoFinal/AlgoritmoGenetico/malva/.cproject new file mode 100644 index 0000000..4d31d90 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/.cproject @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?fileVersion 4.0.0?> + +<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> + <storageModule moduleId="org.eclipse.cdt.core.settings"> + <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1028103499"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1028103499" moduleId="org.eclipse.cdt.core.settings" name="Default"> + <externalSettings/> + <extensions> + <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> + <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + </extensions> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1028103499" name="Default" parent="org.eclipse.cdt.build.core.emptycfg"> + <folderInfo id="cdt.managedbuild.toolchain.gnu.base.1028103499.1127827476" name="/" resourcePath=""> + <toolChain id="cdt.managedbuild.toolchain.gnu.base.765753298" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base"> + <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1817766457" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/> + <builder id="cdt.managedbuild.target.gnu.builder.base.1493464269" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/> + <tool id="cdt.managedbuild.tool.gnu.archiver.base.1457471918" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> + <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1006777203" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"> + <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.224865571" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> + </tool> + <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.2140176745" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"> + <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.587099952" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> + </tool> + <tool id="cdt.managedbuild.tool.gnu.c.linker.base.1988570852" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/> + <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1956065400" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"> + <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.507618374" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> + <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> + <additionalInput kind="additionalinput" paths="$(LIBS)"/> + </inputType> + </tool> + <tool id="cdt.managedbuild.tool.gnu.assembler.base.535458070" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"> + <inputType id="cdt.managedbuild.tool.gnu.assembler.input.584095528" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> + </tool> + </toolChain> + </folderInfo> + </configuration> + </storageModule> + <storageModule moduleId="scannerConfiguration"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> + <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="makefileGenerator"> + <runAction arguments="-E -P -v -dD" command="" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <project id="malva.null.2024921052" name="malva"/> + </storageModule> +</cproject> diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/.gitignore b/ProyectoFinal/AlgoritmoGenetico/malva/.gitignore new file mode 100644 index 0000000..42fcba1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/.gitignore @@ -0,0 +1,6 @@ +.cproject/ +.project/ +.svn/ +.idea/ +.DS_Store + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/.project b/ProyectoFinal/AlgoritmoGenetico/malva/.project new file mode 100644 index 0000000..1bb914c --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/.project @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>Malva</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> + <triggers>clean,full,incremental,</triggers> + <arguments> + <dictionary> + <key>?name?</key> + <value></value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.append_environment</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.autoBuildTarget</key> + <value>all</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.buildArguments</key> + <value></value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.buildCommand</key> + <value>make</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.cleanBuildTarget</key> + <value>clean</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.contents</key> + <value>org.eclipse.cdt.make.core.activeConfigSettings</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableAutoBuild</key> + <value>false</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableCleanBuild</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableFullBuild</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.fullBuildTarget</key> + <value>all</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.stopOnError</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key> + <value>true</value> + </dictionary> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.cdt.core.cnature</nature> + <nature>org.eclipse.cdt.core.ccnature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> + </natures> +</projectDescription> diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/Makefile new file mode 100644 index 0000000..a662e76 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/Makefile @@ -0,0 +1,24 @@ +default: + @echo "Make what? (all, libs, skeletons, clean)" + +all: + (cd inc ; rm -f Mallba) + (cd inc ; ./inc.env) + (cd src ; make all) + (cd lib ; make all) + (cd rep ; make all) + +libs: + (cd inc ; rm -f Mallba) + (cd inc ; ./inc.env) + (cd src ; make all) + (cd lib ; make all) + +skeletons: + (cd rep ; make all) + +clean: + (cd inc ; rm -f Mallba) + (cd src ; make clean) + (cd lib ; make clean) + (cd rep ; make clean) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/br17.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/br17.atsp new file mode 100644 index 0000000..37313b1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/br17.atsp @@ -0,0 +1,42 @@ +NAME: br17 +TYPE: ATSP +COMMENT: 17 city problem (Repetto) +DIMENSION: 17 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999 3 5 48 48 8 8 5 5 3 3 0 3 5 8 8 + 5 + 3 9999 3 48 48 8 8 5 5 0 0 3 0 3 8 8 + 5 + 5 3 9999 72 72 48 48 24 24 3 3 5 3 0 48 48 + 24 + 48 48 74 9999 0 6 6 12 12 48 48 48 48 74 6 6 + 12 + 48 48 74 0 9999 6 6 12 12 48 48 48 48 74 6 6 + 12 + 8 8 50 6 6 9999 0 8 8 8 8 8 8 50 0 0 + 8 + 8 8 50 6 6 0 9999 8 8 8 8 8 8 50 0 0 + 8 + 5 5 26 12 12 8 8 9999 0 5 5 5 5 26 8 8 + 0 + 5 5 26 12 12 8 8 0 9999 5 5 5 5 26 8 8 + 0 + 3 0 3 48 48 8 8 5 5 9999 0 3 0 3 8 8 + 5 + 3 0 3 48 48 8 8 5 5 0 9999 3 0 3 8 8 + 5 + 0 3 5 48 48 8 8 5 5 3 3 9999 3 5 8 8 + 5 + 3 0 3 48 48 8 8 5 5 0 0 3 9999 3 8 8 + 5 + 5 3 0 72 72 48 48 24 24 3 3 5 3 9999 48 48 + 24 + 8 8 50 6 6 0 0 8 8 8 8 8 8 50 9999 0 + 8 + 8 8 50 6 6 0 0 8 8 8 8 8 8 50 0 9999 + 8 + 5 5 26 12 12 8 8 0 0 5 5 5 5 26 8 8 + 9999 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft53.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft53.atsp new file mode 100644 index 0000000..3f81c5b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft53.atsp @@ -0,0 +1,220 @@ +NAME: ft53 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 53 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 223 210 125 245 363 322 388 290 341 267 281 258 247 302 + 325 311 276 392 475 417 324 372 437 610 310 362 333 498 459 + 467 352 199 336 305 172 143 273 292 364 262 296 435 423 433 + 354 509 472 238 185 357 420 344 + 58 9999999 179 100 287 155 116 170 74 137 239 260 234 221 282 + 294 286 251 434 512 409 367 406 410 598 354 353 371 451 490 + 510 389 244 313 291 210 185 318 329 402 297 81 241 215 292 + 308 301 262 207 159 300 214 314 + 60 109 9999999 80 295 246 209 270 174 225 227 179 221 212 262 + 131 117 79 382 431 263 309 321 235 452 355 338 324 497 449 + 360 243 251 140 272 223 189 259 337 388 308 174 340 309 382 + 396 393 355 198 141 201 302 190 + 58 115 98 9999999 285 255 215 279 178 232 154 176 157 136 194 + 219 207 170 429 516 326 366 411 323 517 344 270 368 541 498 + 446 323 244 225 203 214 183 314 278 403 301 183 352 311 391 + 341 410 367 130 76 247 312 236 + 93 58 63 90 9999999 194 160 210 117 174 238 235 231 224 280 + 175 171 133 281 267 221 248 139 286 415 82 136 135 309 264 + 341 293 231 189 75 253 219 306 360 351 340 123 277 248 288 + 323 305 256 155 155 152 248 146 + 531 593 584 499 765 9999999 344 405 309 360 631 654 632 622 679 + 697 685 647 909 992 807 847 887 809 999 789 750 848 763 716 + 763 643 724 539 682 687 664 788 762 881 781 669 832 796 824 + 825 885 838 90 140 164 70 296 + 417 484 469 384 651 55 9999999 257 190 180 519 547 524 506 563 + 586 573 533 803 875 693 733 777 692 888 607 577 662 585 539 + 575 454 611 361 561 581 543 682 645 769 666 546 577 565 493 + 662 653 700 123 177 201 112 343 + 466 521 506 427 693 86 111 9999999 236 275 566 585 505 546 552 + 621 618 574 804 863 594 495 733 735 790 695 673 660 675 627 + 674 556 654 453 615 614 587 685 634 715 707 591 673 659 589 + 690 749 771 154 209 228 147 371 + 243 309 285 205 468 92 54 111 9999999 69 342 366 345 326 385 + 406 391 350 619 705 510 552 599 511 707 501 451 558 472 425 + 471 346 432 253 394 393 373 500 468 588 491 369 532 501 535 + 534 591 549 160 210 233 147 376 + 262 321 302 222 491 81 68 99 32 9999999 359 386 357 340 400 + 424 409 371 639 714 536 569 611 528 728 448 415 504 424 376 + 412 296 450 196 407 419 386 521 488 605 503 389 554 521 554 + 550 614 568 151 204 228 137 359 + 361 416 404 317 435 522 512 544 471 449 9999999 194 179 327 228 + 441 438 392 480 560 357 401 554 557 549 502 453 418 596 544 + 655 532 383 455 396 352 319 359 313 475 437 352 453 467 453 + 373 527 531 78 135 308 392 291 + 182 241 229 134 411 376 341 402 302 314 114 9999999 195 184 246 + 304 288 258 499 583 376 420 494 411 568 395 315 433 612 564 + 511 413 364 311 250 333 305 375 322 493 425 306 469 435 466 + 385 531 481 180 202 333 425 319 + 271 305 315 224 271 354 341 374 301 283 110 105 9999999 164 60 + 276 263 233 313 400 186 241 395 389 387 336 283 255 424 378 + 486 361 220 290 224 179 154 197 138 308 273 182 290 308 285 + 203 363 362 179 231 311 399 293 + 216 277 259 176 281 209 199 227 155 140 35 54 24 9999999 77 + 132 125 79 331 411 204 253 329 246 400 225 147 265 443 397 + 346 239 229 140 80 193 163 211 157 322 288 200 296 320 295 + 215 374 380 94 148 163 255 151 + 275 338 327 242 344 300 293 331 256 241 122 119 99 111 9999999 + 230 220 181 400 479 144 197 371 340 337 327 242 204 384 334 + 446 347 295 238 176 265 235 275 223 262 352 140 303 270 346 + 286 363 315 189 242 261 352 252 + 369 329 451 411 404 405 367 422 324 378 345 393 514 539 561 + 9999999 329 297 264 313 405 312 528 446 596 407 358 316 380 448 + 557 432 286 353 460 163 226 141 278 276 244 379 425 443 412 + 335 494 538 86 146 89 188 75 + 246 305 286 204 416 353 317 374 276 331 181 75 266 252 307 + 24 9999999 310 275 324 158 207 225 136 356 337 270 221 398 348 + 471 348 204 368 315 177 238 151 288 279 260 143 307 267 356 + 351 362 316 99 160 103 199 94 + 278 343 325 243 450 390 353 417 315 367 215 115 301 293 349 + 65 48 9999999 308 365 195 243 261 175 388 381 292 260 430 392 + 292 170 237 79 358 217 274 193 327 318 294 184 346 312 394 + 384 405 355 138 192 141 228 127 + 118 85 249 161 356 148 113 176 78 128 250 149 299 284 345 + 70 86 44 9999999 90 226 277 293 204 425 180 241 241 162 363 + 330 210 271 109 355 227 245 198 337 344 306 146 307 275 359 + 379 368 327 146 202 154 216 140 + 134 93 266 176 364 172 137 191 90 153 255 155 317 301 363 + 93 81 62 31 9999999 227 276 291 207 418 102 160 162 82 291 + 341 227 279 118 370 242 261 216 351 351 322 169 325 294 374 + 392 390 338 157 203 151 225 142 + 306 367 350 263 371 212 171 229 139 186 238 142 322 312 365 + 412 417 378 356 371 9999999 64 239 275 207 196 121 84 252 204 + 558 432 285 370 375 226 223 227 248 138 265 351 377 413 389 + 304 409 368 285 285 330 268 310 + 376 460 449 354 466 305 266 323 227 282 336 230 416 408 462 + 448 448 424 389 372 115 9999999 250 262 307 291 225 171 350 306 + 600 483 332 468 472 322 322 327 342 231 361 429 383 426 401 + 407 415 372 356 306 421 370 410 + 136 225 336 245 369 292 264 314 221 277 328 231 387 368 428 + 221 210 191 160 145 101 122 9999999 251 300 235 212 168 211 299 + 472 353 318 248 239 296 266 314 333 230 351 199 149 187 173 + 203 182 141 121 72 239 339 236 + 223 307 374 280 399 233 198 252 158 213 256 160 343 332 388 + 303 298 273 247 226 36 87 96 9999999 233 217 147 100 270 227 + 350 236 84 331 328 242 246 253 264 165 288 280 238 269 255 + 291 268 217 207 156 332 293 320 + 183 267 381 290 407 296 267 319 223 276 329 226 411 402 460 + 256 251 230 200 185 103 92 61 81 9999999 270 219 173 254 297 + 420 302 153 288 278 316 303 319 339 226 352 241 195 232 208 + 245 226 181 171 117 289 363 272 + 598 658 641 559 823 621 644 551 718 780 695 718 695 682 739 + 689 678 707 946 998 734 782 890 806 924 9999999 71 72 244 195 + 729 609 789 715 750 756 721 819 819 857 838 727 689 726 716 + 744 718 675 315 368 321 407 309 + 536 605 586 502 765 567 585 494 669 719 635 657 639 627 680 + 630 622 652 887 942 766 819 831 748 960 105 9999999 158 334 284 + 811 700 726 709 690 692 660 762 768 882 780 666 779 803 799 + 827 813 768 399 460 404 499 396 + 581 646 628 543 812 611 638 542 710 767 687 701 682 673 724 + 675 664 698 925 982 675 727 871 789 866 135 61 9999999 184 141 + 669 547 771 651 722 737 713 809 808 801 833 682 637 677 650 + 688 665 620 257 312 259 348 246 + 620 677 670 581 853 647 655 579 624 677 717 620 716 702 761 + 718 701 734 835 853 498 547 725 763 696 36 99 98 9999999 218 + 500 375 773 479 775 618 711 711 734 621 714 751 713 752 733 + 768 743 701 86 138 91 182 80 + 586 647 632 545 821 614 634 547 663 716 692 668 681 674 735 + 681 672 698 880 896 547 598 773 791 741 85 67 138 63 9999999 + 546 429 780 522 736 662 714 763 778 669 757 715 762 800 781 + 815 796 752 132 184 135 224 119 + 500 712 702 613 737 847 812 871 776 829 756 770 747 737 792 + 812 803 764 879 958 908 814 861 925 1103 797 782 822 987 943 + 9999999 653 691 559 793 659 628 764 774 849 753 784 927 911 917 + 838 998 963 724 677 843 911 833 + 619 720 707 621 850 685 705 614 723 772 764 725 756 746 807 + 758 739 766 883 862 596 502 740 747 791 220 134 281 447 407 + 136 9999999 485 118 815 775 752 815 830 717 853 673 700 620 795 + 721 778 815 520 573 528 621 514 + 768 870 853 766 1000 831 853 762 872 923 905 870 910 892 956 + 904 893 916 1032 1015 742 648 884 901 936 369 279 431 598 551 + 285 166 9999999 262 964 931 898 966 983 866 1000 819 854 775 946 + 870 926 964 669 725 676 766 664 + 722 816 801 722 951 786 805 710 820 873 860 820 859 848 901 + 858 847 875 978 959 702 600 837 852 894 322 232 376 554 510 + 235 119 381 9999999 915 879 852 912 931 825 950 773 797 722 902 + 821 871 923 625 678 621 712 611 + 730 693 861 768 883 538 493 738 678 664 619 759 779 894 825 + 678 689 652 619 706 838 784 898 818 1026 520 435 582 752 705 + 274 316 169 394 9999999 642 698 617 755 754 722 756 896 889 889 + 815 974 932 95 144 99 188 84 + 341 300 311 337 257 375 338 399 305 361 254 374 427 467 474 + 297 306 267 237 315 264 163 384 416 462 291 215 178 349 302 + 461 345 194 332 324 9999999 135 116 137 210 109 238 275 296 272 + 199 358 396 124 73 243 335 231 + 371 325 341 374 292 403 360 425 331 382 139 312 308 451 352 + 323 335 303 266 345 297 195 413 442 485 315 246 204 373 333 + 341 222 81 329 351 48 9999999 142 158 231 133 260 307 322 301 + 226 386 423 152 102 271 366 264 + 247 200 330 286 276 274 236 300 203 257 218 273 383 410 434 + 192 207 168 139 218 282 179 395 324 472 303 231 185 280 321 + 428 309 157 230 334 40 93 9999999 154 158 120 254 293 311 291 + 216 367 408 148 98 269 337 261 + 225 179 195 223 140 320 280 337 249 301 147 321 321 346 367 + 250 264 221 188 268 301 214 265 382 499 203 265 214 337 345 + 361 241 88 277 202 61 23 67 9999999 207 147 117 157 174 152 + 76 238 271 168 116 279 371 268 + 331 288 305 330 253 178 139 379 292 304 221 360 395 459 433 + 289 301 261 227 311 304 206 374 415 491 311 255 215 370 335 + 433 315 166 317 315 96 98 110 125 9999999 144 225 267 285 265 + 188 341 383 215 162 329 241 317 + 250 214 223 255 174 287 245 305 209 262 165 283 335 373 385 + 211 218 177 152 226 170 79 297 331 365 204 132 85 260 207 + 373 256 109 243 234 54 47 26 48 118 9999999 143 188 205 181 + 108 260 306 167 116 279 341 271 + 529 587 576 488 738 428 456 355 574 613 548 618 623 605 669 + 593 602 569 537 613 494 548 561 477 693 403 454 461 380 590 + 556 594 445 628 289 509 566 476 613 616 586 9999999 172 144 227 + 241 232 189 257 204 370 466 358 + 412 441 461 373 592 269 287 194 421 448 495 512 509 497 556 + 437 447 406 373 454 427 480 490 410 628 339 400 398 322 530 + 496 532 381 464 229 360 418 335 464 470 436 61 9999999 107 158 + 135 84 131 212 168 309 323 297 + 393 453 440 353 622 347 370 272 497 527 498 519 495 478 544 + 516 527 488 452 537 459 515 520 442 659 426 478 475 399 606 + 528 560 413 547 261 433 497 410 551 553 515 67 94 9999999 190 + 115 163 211 128 74 245 338 239 + 464 520 508 421 648 353 370 275 401 464 505 407 558 546 605 + 520 533 489 457 478 282 334 346 262 483 425 398 353 401 479 + 343 387 234 464 86 447 497 415 518 408 528 65 98 76 9999999 + 181 170 221 161 147 167 260 152 + 296 360 344 258 527 348 375 276 427 477 394 415 398 385 440 + 462 449 406 459 534 360 410 430 338 552 422 475 426 398 551 + 426 463 315 465 162 442 423 422 526 491 523 50 94 112 94 + 9999999 173 213 226 178 240 330 232 + 339 403 387 301 524 359 387 286 443 495 435 462 436 426 479 + 443 453 409 377 457 354 412 422 331 554 387 443 420 364 546 + 423 456 310 473 160 283 338 264 394 397 369 31 110 29 88 + 58 9999999 184 144 97 240 329 221 + 364 426 411 320 564 276 299 211 425 461 379 445 465 453 511 + 448 460 423 386 469 314 364 378 295 510 220 278 282 203 410 + 383 414 272 478 113 327 383 306 434 443 406 76 26 67 47 + 86 61 9999999 177 134 193 294 184 + 1551 1527 1596 1509 1784 1572 1562 1504 1522 1513 1653 1593 1650 1634 1695 + 1512 1530 1489 1455 1532 1512 1560 1549 1582 1505 1050 1026 1104 1028 978 + 1419 1297 1562 1197 1678 1635 1678 1643 1747 1637 1717 1578 1617 1634 1614 + 1534 1693 1672 9999999 73 233 330 224 + 1599 1569 1649 1566 1834 1527 1515 1543 1478 1463 1706 1641 1621 1687 1673 + 1571 1578 1543 1504 1585 1548 1530 1496 1520 1458 1102 1078 1154 1079 1027 + 1360 1248 1506 1144 1628 1682 1727 1689 1754 1666 1775 1517 1568 1582 1557 + 1486 1638 1621 60 9999999 188 274 169 + 1504 1464 1629 1541 1713 1598 1564 1542 1528 1543 1552 1549 1454 1603 1497 + 1550 1557 1526 1490 1566 1539 1566 1579 1609 1534 1080 1062 1144 1060 1010 + 1192 1071 1343 977 1621 1627 1593 1632 1577 1663 1715 1514 1553 1578 1548 + 1477 1627 1670 44 100 9999999 272 159 + 1505 1534 1545 1464 1705 1550 1572 1487 1533 1523 1607 1601 1548 1586 1590 + 1532 1543 1503 1470 1547 1519 1573 1563 1549 1517 1057 1045 1120 1040 993 + 1280 1168 1432 1060 1366 1462 1581 1563 1584 1648 1551 1255 1302 1319 1298 + 1224 1380 1412 24 79 106 9999999 240 + 1520 1472 1612 1526 1722 1589 1574 1517 1528 1520 1559 1558 1466 1616 1513 + 1530 1536 1501 1466 1544 1517 1573 1562 1593 1518 1056 1044 1116 1036 992 + 1206 1088 1352 986 1469 1571 1607 1642 1595 1643 1658 1362 1411 1429 1401 + 1325 1479 1516 21 80 29 118 9999999 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft70.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft70.atsp new file mode 100644 index 0000000..75cacb6 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ft70.atsp @@ -0,0 +1,358 @@ +NAME: ft70 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 70 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 375 1000 1011 853 950 936 1027 1101 1235 1279 1109 1141 976 1389 + 858 1368 1110 1263 1435 1091 936 1047 962 1079 1083 826 926 1004 1203 + 1037 1105 1229 986 1227 1096 1235 973 753 1165 1518 1064 1285 1149 1312 + 914 1161 1349 1418 1515 1170 966 1112 1049 1064 912 901 1040 1086 1177 + 1118 1239 1103 1203 1094 1237 1143 1195 1293 1229 + 609 9999999 1068 980 1029 976 1068 1144 1100 1342 1262 1097 1304 1217 1494 + 960 1214 1233 1040 1175 1122 1237 1133 1031 1192 1004 1005 1087 1119 1109 + 1019 1087 1248 1257 1196 1061 1284 1142 951 1117 1329 1320 1284 1340 1282 + 934 1207 1200 1559 1717 1190 1168 1213 1144 1196 1317 1112 1048 1259 1008 + 871 1326 1455 977 1139 1335 974 1352 1468 1057 + 669 419 9999999 888 528 955 989 989 794 1185 1055 987 933 1009 1022 + 709 1124 1137 1203 1048 984 845 657 600 880 998 874 739 603 1042 + 939 1024 986 813 1136 872 963 1013 710 801 1189 1126 977 1102 1069 + 683 1102 1253 1316 1373 978 1046 881 998 1001 948 751 982 1092 881 + 829 1335 1082 1071 1053 941 889 1100 1164 970 + 665 645 664 9999999 559 491 528 592 505 769 680 576 793 724 996 + 796 898 755 525 1002 639 629 676 635 694 854 562 543 524 790 + 495 632 968 715 923 665 809 811 496 794 1031 759 714 829 764 + 609 504 1040 903 986 544 703 543 942 814 712 794 546 741 737 + 430 926 1047 660 686 558 632 944 808 890 + 632 606 506 676 9999999 659 742 781 582 926 778 865 868 620 798 + 499 996 787 883 792 858 615 438 483 671 523 527 557 562 661 + 544 609 871 587 837 541 787 571 558 594 1038 910 761 873 765 + 648 651 970 1026 1307 811 669 749 621 548 748 649 697 923 652 + 707 879 968 617 879 706 773 1035 944 863 + 712 373 621 441 416 9999999 441 666 565 524 541 507 803 574 680 + 613 739 875 860 1018 699 697 576 691 801 761 606 511 597 805 + 619 790 808 798 965 654 698 636 676 842 986 886 910 690 897 + 464 556 1062 1178 1097 697 830 869 627 821 661 784 848 868 562 + 623 927 823 544 475 852 674 803 814 786 + 412 702 566 534 473 744 9999999 623 690 765 770 526 699 752 986 + 492 577 596 733 746 598 672 681 715 676 762 608 590 522 782 + 694 769 976 723 700 704 923 692 467 751 964 813 806 818 538 + 485 700 865 996 1234 548 645 766 800 759 606 786 681 651 549 + 482 901 792 702 544 726 456 902 925 827 + 826 666 682 535 668 660 705 9999999 688 861 755 706 766 495 693 + 913 1001 768 727 1046 724 894 748 927 1051 816 863 743 654 822 + 872 952 1094 786 839 968 1126 1039 662 789 1152 1080 798 884 852 + 986 622 1202 1255 1072 813 980 841 984 929 872 868 893 810 876 + 791 1090 1030 708 822 879 577 1058 896 1107 + 874 915 804 786 736 873 725 491 9999999 729 749 578 641 757 747 + 942 943 1023 937 1170 746 1066 943 808 943 893 1064 909 1005 1095 + 803 1046 1041 1079 933 958 1078 1100 820 845 1225 975 971 755 1020 + 956 690 1241 1129 939 820 922 981 1105 961 1136 922 905 956 1001 + 785 1087 1012 905 839 921 753 913 755 981 + 806 919 992 826 940 683 913 470 456 9999999 728 555 653 586 802 + 962 896 1137 811 950 972 1005 797 934 1070 975 857 887 791 1055 + 852 946 1049 983 1037 1094 1111 1122 807 1019 1342 1160 883 814 1119 + 870 932 1124 1364 910 782 1104 1072 1063 938 929 939 926 1084 831 + 864 1151 1137 618 757 828 481 786 740 980 + 773 960 1030 780 702 970 966 697 559 472 9999999 803 609 743 612 + 1100 974 970 970 1162 825 989 910 954 1156 1107 974 1092 1059 908 + 944 1118 1050 1023 1062 975 1172 1154 833 988 1312 1045 1154 592 1182 + 879 815 1097 1368 1193 1001 1106 1003 1026 1130 1007 967 1085 973 922 + 1006 1271 1285 505 737 875 689 1027 842 1123 + 805 663 762 640 787 632 870 475 381 585 501 9999999 628 577 806 + 846 909 1021 880 1087 1009 934 1024 932 905 990 1032 994 847 1121 + 830 911 1138 1018 1134 745 854 851 740 818 965 740 868 514 883 + 968 735 1046 1307 948 694 847 1014 1023 1016 949 1047 882 1138 744 + 844 1307 1154 657 721 856 664 927 730 954 + 910 777 916 662 851 937 745 695 527 528 402 533 9999999 909 669 + 911 1044 1129 938 1099 873 1187 888 956 1193 1126 1172 1026 800 979 + 1119 1041 1235 1154 1195 981 1185 1111 858 1143 1435 1001 1012 833 1205 + 1129 1027 1087 1332 1057 968 1110 849 1089 1207 1026 1111 993 902 1075 + 893 1112 1073 474 624 684 773 1074 750 1060 + 1058 766 1030 850 962 822 865 655 471 625 580 655 608 9999999 703 + 975 1238 1063 991 1213 885 987 1023 942 1137 956 889 923 935 1214 + 1023 1063 1339 983 1046 1040 1025 1180 956 932 1412 906 1006 853 1155 + 871 836 1155 1480 1172 1011 1157 1050 1274 1125 975 950 1092 1001 858 + 795 1295 1039 615 856 948 721 886 799 1149 + 935 773 823 884 766 684 735 663 571 613 479 685 682 643 9999999 + 901 1005 902 877 1117 842 878 963 1038 1156 914 984 1052 999 1176 + 963 1175 1245 942 1114 997 1091 1096 802 990 1247 1022 876 799 949 + 948 890 1137 1274 912 759 898 1094 1040 1175 969 1116 1076 1045 808 + 837 1244 1071 398 656 762 757 998 786 1207 + 647 593 614 715 510 570 622 492 696 670 681 532 710 716 1007 + 9999999 1025 786 989 812 936 662 825 588 842 916 765 563 573 985 + 908 794 825 759 1062 882 1084 794 743 918 1318 931 1050 611 913 + 809 582 742 1357 1068 731 839 816 718 828 975 707 743 830 869 + 897 1194 1054 918 832 723 785 942 910 985 + 675 703 683 693 611 725 910 776 662 870 943 557 856 907 878 + 375 9999999 699 582 560 728 970 601 719 799 831 843 696 625 848 + 718 681 907 695 1005 688 946 811 699 969 1136 716 788 958 656 + 802 709 627 1002 1098 690 559 685 752 689 784 926 790 864 776 + 936 1195 1008 699 845 833 687 940 972 688 + 852 654 736 652 626 608 767 795 635 851 827 876 673 663 692 + 567 555 9999999 760 648 682 734 458 790 645 480 679 676 665 805 + 767 812 845 861 1080 723 838 713 675 777 1154 830 628 974 706 + 608 855 783 976 1245 920 684 781 727 678 600 809 806 817 766 + 871 1144 1058 616 862 762 836 1124 979 729 + 676 602 822 793 723 660 862 636 719 828 885 742 942 880 967 + 492 606 587 9999999 551 710 955 743 877 672 582 785 746 707 821 + 477 502 898 734 958 782 853 577 621 666 1088 883 770 921 868 + 973 877 626 1113 1233 654 709 888 781 941 740 1006 685 675 864 + 902 926 677 808 800 874 931 991 1050 781 + 820 868 737 766 816 800 744 861 631 819 966 775 1015 755 855 + 709 774 617 494 9999999 854 677 563 725 799 482 799 770 742 816 + 506 755 866 710 997 639 856 556 800 771 879 492 692 931 626 + 779 553 526 1047 1112 528 455 754 744 755 483 843 527 636 725 + 836 837 800 932 917 650 831 1038 864 836 + 844 767 714 878 815 561 758 717 752 704 821 642 944 600 808 + 651 662 398 377 793 9999999 780 726 868 582 686 768 937 914 680 + 628 688 762 749 931 745 890 786 747 555 902 872 694 975 763 + 699 816 756 1192 1166 912 868 809 929 994 917 819 654 871 691 + 921 906 796 568 558 711 688 1092 990 912 + 894 676 988 739 891 721 818 957 878 880 788 849 981 721 828 + 806 1065 982 793 913 824 9999999 797 747 545 706 498 582 690 912 + 904 985 972 680 969 620 937 763 775 755 1315 1000 787 988 1119 + 645 770 1092 1354 1337 784 713 829 888 704 664 712 824 932 872 + 707 1022 922 611 867 553 749 1007 773 932 + 721 892 856 716 760 758 739 640 635 787 908 803 876 716 717 + 727 1099 1018 1015 1038 798 492 9999999 574 651 395 666 707 827 927 + 674 995 1005 811 870 544 932 926 914 738 1173 918 984 1028 1123 + 885 685 1145 1252 1354 954 954 765 748 755 742 738 895 836 869 + 975 1179 961 644 737 691 666 1073 743 1067 + 811 753 647 617 776 593 724 835 588 768 645 641 601 745 927 + 434 997 749 658 990 798 550 777 9999999 632 594 483 744 646 644 + 519 609 787 674 909 646 758 609 701 740 1067 657 780 852 788 + 773 612 1035 1194 1225 586 644 514 633 625 505 581 728 848 725 + 917 771 644 536 707 754 640 793 848 876 + 678 604 575 573 490 579 453 828 776 847 727 786 622 630 925 + 672 757 817 646 794 700 630 627 515 9999999 652 611 486 514 598 + 468 775 798 501 727 793 827 811 726 802 1006 692 697 696 943 + 586 675 922 1063 1286 579 707 717 737 682 559 456 710 923 515 + 621 894 792 556 683 409 512 751 647 847 + 731 732 725 489 589 589 680 626 799 712 803 556 656 438 737 + 666 872 817 972 1107 711 656 552 602 514 9999999 765 697 666 670 + 595 745 834 849 855 432 1002 871 869 682 1258 747 712 946 993 + 563 846 1123 1189 1187 835 860 688 846 856 780 678 809 878 712 + 871 1082 1030 756 798 668 589 839 642 790 + 772 738 682 764 816 664 570 905 717 697 860 848 948 547 1005 + 756 991 1006 723 900 799 666 656 646 624 610 9999999 775 651 764 + 687 734 833 626 1018 519 1110 936 871 695 1008 913 950 969 1059 + 776 615 1105 1347 1195 622 733 632 741 717 581 724 762 772 788 + 764 948 879 738 841 774 827 1001 663 938 + 910 887 809 662 731 716 593 859 803 630 677 712 760 547 708 + 628 1054 891 742 867 856 515 331 512 470 531 496 9999999 669 660 + 795 662 777 783 801 656 996 716 750 724 1176 908 752 872 770 + 600 712 882 1081 1311 616 698 615 799 760 764 676 643 640 545 + 858 1006 901 542 685 582 663 1021 936 702 + 908 545 674 582 724 560 725 639 563 628 676 630 602 733 902 + 440 949 750 837 902 801 497 619 561 750 630 492 616 9999999 804 + 476 746 844 730 781 512 864 683 834 623 1008 800 712 703 822 + 452 805 986 977 1197 633 616 575 690 463 555 588 608 675 596 + 978 1029 696 670 782 846 884 838 730 616 + 1085 780 885 770 888 874 926 884 638 611 717 693 577 669 766 + 852 1054 1168 1098 1000 1039 613 663 612 673 748 758 622 712 9999999 + 787 986 879 775 928 787 1129 823 987 775 1338 1010 997 845 862 + 892 916 1174 1191 1161 879 720 973 841 680 698 888 907 801 827 + 998 998 986 519 624 615 780 628 575 596 + 878 696 874 663 770 717 884 655 731 732 732 902 803 960 869 + 500 778 784 861 857 792 885 630 762 761 613 752 690 885 590 + 9999999 838 742 805 716 519 574 406 632 501 925 509 627 924 671 + 716 547 874 1240 1251 516 662 700 809 812 852 788 1006 882 842 + 881 1154 849 557 899 756 683 906 745 646 + 813 784 877 869 876 781 1000 859 706 634 754 805 707 746 843 + 553 822 959 704 833 949 938 822 920 966 816 808 793 784 648 + 370 9999999 670 692 782 511 626 580 693 589 991 506 698 870 649 + 842 557 1083 945 1276 576 587 698 957 904 1055 972 744 529 728 + 644 854 526 676 903 695 669 858 668 701 + 651 673 934 789 845 801 764 715 548 747 612 704 451 772 786 + 642 1139 871 941 960 797 811 566 708 687 632 597 458 945 437 + 530 661 9999999 633 664 617 743 643 636 596 960 572 791 635 543 + 830 621 957 801 1228 802 802 874 825 886 944 873 728 593 677 + 976 922 664 742 608 676 755 600 693 421 + 929 854 813 724 841 643 752 877 605 730 710 834 647 690 1005 + 492 1060 804 895 938 718 972 667 849 704 740 877 645 746 514 + 475 423 475 9999999 589 543 730 578 609 667 978 586 662 795 697 + 778 750 982 886 1100 759 535 802 813 871 921 1022 809 605 602 + 707 873 678 732 903 753 683 683 656 671 + 755 447 1127 804 1000 723 994 736 822 832 875 733 776 786 766 + 778 957 916 992 1118 932 801 826 680 994 749 756 787 999 623 + 636 564 458 684 9999999 824 757 611 868 726 1103 815 615 992 711 + 845 768 1137 853 1159 891 792 862 842 834 895 875 962 788 602 + 850 810 801 778 879 898 664 874 878 686 + 1858 1976 1887 1686 1781 1843 1899 1634 1777 1688 1743 1598 1732 1402 1622 + 1612 2196 2109 2183 2035 1905 2180 1912 1921 1990 2028 2069 1981 1926 1987 + 2098 2050 1948 2016 1931 9999999 1262 1205 1130 1200 1605 1232 1167 1689 1926 + 2031 1923 2276 2160 2197 1858 1820 1924 1965 1932 1846 2129 1716 1877 1731 + 1769 2022 2157 1179 1230 1366 1386 1452 1320 1302 + 1023 1198 1259 1228 1416 1113 1340 1334 1089 1213 1244 1135 1397 914 1167 + 1038 1399 1487 1368 1555 1444 1164 1179 1341 1207 1362 1318 1267 1166 1195 + 1360 1142 1318 1300 1313 642 9999999 570 692 492 845 626 451 1350 1235 + 1232 1202 1404 1647 1647 1182 1040 1242 1281 1253 1205 1376 1280 1191 1120 + 1173 1432 1339 727 734 847 820 822 718 557 + 1203 1180 1235 1260 1198 1296 1196 1297 1266 1350 1316 1346 1498 1353 1361 + 1120 1501 1386 1508 1532 1483 1369 1348 1271 1430 1305 1405 1210 1393 1494 + 1353 1596 1381 1423 1319 742 864 9999999 786 711 1009 841 876 1334 1284 + 1408 1321 1587 1572 1730 1453 1323 1424 1514 1339 1376 1518 1095 1103 1095 + 947 1540 1562 515 819 601 716 649 648 526 + 1137 1280 1415 1140 1466 1182 1287 1125 1146 1204 1134 1012 1215 788 1310 + 1290 1483 1543 1527 1605 1548 1426 1418 1461 1494 1605 1516 1484 1438 1644 + 1347 1455 1452 1311 1481 530 787 731 9999999 558 1148 886 719 1126 1300 + 1458 1332 1705 1571 1622 1521 1289 1388 1339 1421 1326 1425 1185 1349 1149 + 1148 1646 1506 874 974 697 789 812 965 653 + 1044 962 1287 1247 1101 1285 1134 1081 1249 1282 1241 1225 1197 1129 1382 + 1128 1326 1264 1422 1308 1409 1197 1215 1096 1038 1190 1330 1210 1147 1424 + 1229 1126 1325 1315 1466 650 702 332 576 9999999 712 403 448 1354 1125 + 1256 1268 1409 1514 1535 1239 1018 1029 1219 1127 1140 1347 1217 1202 1277 + 944 1469 1354 614 648 572 675 754 838 514 + 1071 1028 1447 1400 1224 1301 1366 1154 1187 1060 1056 1278 1224 1152 1141 + 1110 1471 1481 1432 1546 1213 1158 1123 1050 1148 1047 1159 1127 1214 959 + 1067 1112 925 1170 1050 671 548 682 583 547 9999999 747 650 1060 861 + 708 1233 1670 1196 1380 1110 1214 1230 1144 1313 1159 1207 1138 1069 1158 + 1045 1409 1022 645 951 700 897 718 810 751 + 1050 882 1342 1161 1325 1217 1275 1168 1197 1192 1178 1299 1322 1062 1302 + 1131 1501 1478 1236 1330 1422 1063 1244 931 954 1228 1073 1092 1210 1338 + 1333 1161 1191 1241 1280 811 515 464 601 721 673 9999999 580 1322 1111 + 1156 1295 1583 1473 1836 1096 1289 1372 1242 1128 1113 1277 1091 1258 1215 + 928 1601 1381 553 604 827 763 752 607 602 + 1118 1166 1415 1307 1108 1232 1357 1272 1258 1393 1412 1346 1249 1158 1211 + 1082 1498 1420 1245 1451 1139 1208 1146 1007 965 1377 1144 1251 1092 1159 + 1167 1169 1378 1072 1209 569 648 652 700 699 722 349 9999999 1288 1274 + 1108 1056 1375 1471 1755 1239 1157 1095 1104 1176 1096 1378 1110 1231 1050 + 1253 1566 1279 684 600 690 753 896 824 490 + 1120 1026 1104 1029 1039 1144 875 1148 1176 1140 1117 944 1065 1279 1132 + 1079 1329 1250 1270 1470 1094 1095 973 1079 1243 1148 1235 988 1039 807 + 953 912 1069 1152 879 989 1326 1181 1080 1152 1508 1097 1254 9999999 1029 + 1282 967 1259 1103 762 1172 1106 1289 1155 1229 1137 1257 1157 1211 1087 + 1035 1381 1100 713 582 646 679 705 638 814 + 1369 1236 1472 1205 1340 1223 1195 1303 1266 1524 1284 1353 1294 1243 1534 + 1132 1252 1399 1376 1400 1504 1185 1081 1080 1336 1235 1127 965 1366 1145 + 1379 1342 1244 1257 1159 1023 1543 1256 1457 1439 1619 1341 1464 765 9999999 + 1251 937 1100 770 937 1185 1213 1297 1468 1344 1258 1387 1377 1352 1221 + 1439 1551 1341 783 794 837 971 896 818 1223 + 1562 1364 1372 1207 1311 1293 1237 1450 1295 1368 1284 1359 1349 1471 1459 + 1602 1502 1487 1531 1802 1496 1493 1363 1448 1562 1356 1530 1300 1568 1290 + 1311 1225 1346 1614 1272 1113 1509 1429 1372 1459 1608 1528 1451 821 1126 + 9999999 1261 1616 1183 1039 1341 1539 1586 1500 1561 1585 1420 1221 1005 1231 + 1323 1135 1045 883 937 1058 981 1022 842 1098 + 1663 1689 1725 1516 1698 1648 1597 1522 1702 1575 1471 1725 1775 1839 1556 + 1778 1900 1901 1845 1982 1753 1932 1593 1793 1768 1808 1694 1732 1700 1705 + 1616 1638 1589 1964 1692 1593 1727 1624 1691 1833 1787 1547 1663 935 1285 + 639 9999999 1559 1194 1452 1645 1659 1879 1792 1793 1757 1775 1413 1283 1377 + 1409 1456 1211 1301 1260 1246 1203 1182 1215 1502 + 1207 1142 1416 1333 1350 1096 1469 1331 1341 1332 1410 1418 1320 1257 1638 + 1404 1293 1419 1272 1332 1318 1518 1288 1272 1403 1328 1482 1452 1402 1086 + 1186 1338 1364 978 1246 1238 1384 1239 1298 1172 1521 1398 1248 967 1429 + 1175 1042 9999999 1055 1124 1039 1181 1235 1126 1238 971 1373 1390 1259 1411 + 1277 1448 1192 1210 1120 1181 1138 1335 1176 1215 + 1080 1222 1165 1152 1249 1021 974 1077 1082 1231 1338 1172 1072 1394 1483 + 1154 915 1295 1308 1203 1272 1143 1187 1058 1309 1164 1058 1304 1248 1046 + 1127 1034 1160 1227 1127 931 1474 1106 1127 1234 1597 1225 1238 398 1065 + 906 791 1011 9999999 841 1112 1254 1240 1325 1411 1294 1387 1147 1209 1187 + 1076 1350 1169 829 685 838 634 827 601 1021 + 1220 1228 1212 1160 1249 1025 1072 943 843 1070 913 1120 1022 1014 857 + 1410 1417 1291 1131 1561 1193 1271 1241 1199 1450 1411 1352 1226 1209 986 + 1194 1152 1041 1327 1072 550 1437 1123 1260 1166 1555 1361 1309 571 1249 + 1292 1123 765 791 9999999 1043 1133 1215 1467 1472 1387 1274 1205 1152 1302 + 1155 1467 1234 839 531 806 698 680 720 1023 + 885 859 1096 981 946 697 832 762 749 852 779 875 995 769 838 + 781 697 536 491 743 655 870 615 796 746 719 891 983 881 947 + 847 700 1057 627 1040 606 785 628 672 821 1151 777 781 1053 945 + 939 799 880 1149 1217 9999999 734 612 641 787 762 731 787 939 995 + 830 1077 821 579 903 717 875 1145 870 684 + 1035 921 1037 989 943 922 1038 886 858 1008 1056 852 1085 931 1017 + 725 863 857 642 877 723 996 781 970 926 850 977 935 1041 855 + 973 806 880 731 1173 786 988 844 765 951 1120 936 831 1147 1073 + 709 513 1082 1269 1397 455 9999999 761 682 911 859 822 1071 949 914 + 1180 928 992 866 810 891 685 1151 1144 785 + 769 779 788 757 686 749 800 793 930 793 913 690 965 526 837 + 679 953 882 639 983 847 587 624 657 708 503 807 888 738 929 + 676 888 859 798 818 703 931 594 631 866 1043 984 669 996 976 + 753 578 1144 1078 1291 535 525 9999999 716 586 573 600 810 813 776 + 927 1135 916 831 811 864 958 1063 835 578 + 723 663 638 515 582 691 689 738 744 828 936 626 842 698 1059 + 598 829 756 656 981 636 640 627 606 774 550 601 554 784 745 + 610 873 974 648 893 618 866 585 471 807 1138 803 742 684 1011 + 779 707 938 1154 1056 617 540 506 9999999 686 788 914 877 965 762 + 831 1078 997 752 856 694 717 898 908 690 + 753 653 755 855 820 700 852 884 903 878 562 874 759 772 759 + 960 848 930 839 1024 661 873 664 707 629 764 954 943 691 939 + 839 861 1012 748 907 853 891 792 660 741 1217 1039 912 945 591 + 868 773 1071 994 1228 605 566 381 563 9999999 759 686 482 736 513 + 752 999 810 851 957 967 725 1131 909 685 + 649 622 595 759 775 682 844 678 630 823 826 676 898 573 1009 + 761 669 738 681 888 641 840 580 710 777 511 688 716 808 523 + 433 658 742 641 899 662 727 656 690 648 824 707 642 954 653 + 907 676 818 936 1102 407 390 645 482 560 9999999 865 701 774 776 + 911 746 846 672 626 794 693 805 829 585 + 739 602 661 823 656 690 849 719 676 486 494 695 487 755 758 + 562 719 687 789 756 635 743 648 762 765 562 779 833 788 637 + 490 661 641 395 724 711 673 754 619 568 1014 559 536 802 656 + 647 654 986 867 1145 360 545 561 408 457 417 9999999 669 678 637 + 866 901 713 466 590 890 546 945 772 572 + 807 776 908 1020 667 1005 973 912 861 1184 1074 989 1111 1025 1102 + 833 1235 1076 1128 1235 1068 959 677 682 981 952 977 660 793 882 + 758 867 1157 946 1085 956 1118 984 715 892 1172 1190 1005 713 476 + 873 1042 1351 790 1078 1069 783 978 1030 1009 798 764 9999999 675 992 + 1150 1146 1048 859 997 947 789 978 798 1035 + 1047 1017 869 1092 940 1142 985 1163 1165 1249 1064 1303 1003 857 1263 + 843 1229 1183 1188 1192 1164 917 847 861 898 840 862 801 834 1051 + 1035 961 1283 1104 1152 1047 1259 1083 1020 971 1529 1078 1268 889 760 + 1074 1244 1282 939 1191 1053 1097 1154 1020 1117 1191 897 676 9999999 909 + 1120 1207 1040 937 965 927 965 1041 871 1276 + 1081 904 825 949 716 1083 990 847 762 760 496 877 949 1036 930 + 838 909 1029 844 1127 1095 825 914 1019 977 1011 881 861 880 1128 + 1026 833 977 1025 887 1122 1063 1136 939 918 1408 911 1040 800 621 + 1072 1012 1237 1070 1103 914 934 990 1063 900 1165 1056 496 584 9999999 + 698 963 854 749 800 797 695 1126 906 1063 + 1006 952 726 975 904 1099 970 718 724 717 792 865 1091 947 799 + 1019 986 1153 817 962 1142 821 753 947 1049 854 1037 771 990 849 + 997 762 876 887 706 1021 1048 951 815 1010 1139 945 849 735 540 + 830 1132 1224 873 1185 1030 1111 914 997 1145 1084 1019 657 701 503 + 9999999 778 818 489 568 766 516 1044 925 782 + 1050 835 996 835 678 941 962 816 678 689 674 941 1082 1102 939 + 940 806 980 730 1033 897 948 938 744 874 771 851 887 816 1099 + 854 946 871 890 877 921 763 792 777 763 974 649 786 836 649 + 926 988 1233 1064 1136 964 878 911 720 668 945 1075 536 538 521 + 718 9999999 890 679 736 761 574 1004 940 774 + 962 1085 996 1061 875 1138 910 891 667 805 532 810 936 1081 835 + 872 885 1005 724 1038 1104 932 725 961 1082 869 985 773 796 1099 + 1085 877 1078 1011 778 957 867 762 795 935 1018 826 816 782 577 + 1090 1033 1010 839 1271 1019 1040 1051 968 862 1025 967 433 389 404 + 679 498 9999999 686 850 801 816 1138 902 821 + 1927 1983 1997 1959 2157 2170 2045 2221 2159 2159 2264 2231 2046 1910 2335 + 2056 1966 1987 2199 1989 2150 1950 2147 2255 2087 1995 2160 2226 2154 2039 + 2188 2019 1977 2218 2043 1606 1494 1604 1558 1461 1832 1398 1580 1490 1921 + 1875 1859 1955 1418 1962 1990 2011 2198 2146 2312 2146 2251 2255 2335 2273 + 1991 2373 2181 9999999 486 752 415 1018 923 916 + 2129 2282 2240 2197 2273 2185 2270 2203 2402 2253 2413 2255 2321 2107 2259 + 2100 2034 2205 2269 2219 2272 1814 2239 2166 2161 2217 2002 2092 1996 2253 + 2289 2170 2251 2071 2307 1728 1627 1569 1622 1533 1960 1795 1579 1787 2181 + 2233 1937 1875 1408 1993 2240 2289 2217 2316 2263 2346 2263 2179 2266 2332 + 2320 2588 2275 691 9999999 978 787 1209 881 963 + 1923 1990 2082 1882 1829 2080 1929 1977 2138 2100 2001 1977 2120 1947 2141 + 1944 1927 1964 2176 2114 2267 1893 1869 2108 2138 1996 1960 1994 2081 2130 + 2058 1978 2068 2200 2045 1592 1451 1525 1531 1474 1911 1520 1660 1526 2080 + 1956 1578 1999 1565 1918 2259 2279 2017 2238 2231 2088 2038 2067 1866 2106 + 2195 2452 2069 471 566 9999999 433 645 552 719 + 2271 2110 2196 2019 2099 2085 2033 2056 2015 2050 2189 2107 1949 2157 2134 + 2041 2197 2053 2072 1750 2205 2042 2120 2107 1977 1940 2022 2106 2040 1906 + 1854 2049 1808 2076 2052 1577 1404 1441 1507 1539 1976 1675 1460 1687 2010 + 2212 1746 1956 1659 2021 1959 1995 1995 1916 2095 1960 2185 1916 1993 2040 + 2181 2270 2134 463 443 618 9999999 909 816 871 + 2170 2021 2292 1997 2202 2012 2037 2216 2244 2226 2018 2067 2008 2096 2295 + 2040 2053 2053 2003 2067 1978 2182 2142 2157 2151 2089 2183 1900 2175 1963 + 2121 2044 2065 1883 2122 1473 1527 1532 1468 1613 1794 1644 1634 1441 1840 + 2122 1932 2006 1403 1761 1915 1889 1926 1994 1983 1999 2031 1926 1662 2008 + 2318 2310 2285 386 627 627 759 9999999 712 749 + 2243 2278 2112 2059 2217 2099 2293 2166 2311 2106 2136 2348 1952 1959 2380 + 2041 2253 1954 2053 1801 2215 2009 2104 2283 2228 2008 1935 2167 2264 2064 + 2026 2138 1856 2037 1875 1612 1581 1757 1682 1713 1918 1738 1632 1726 2061 + 2041 1934 2100 1601 2052 2200 2048 2068 1979 2066 1989 2081 1967 1715 2213 + 2352 2395 2113 588 640 641 461 682 9999999 757 + 2058 2030 2049 2062 2021 2048 2033 2126 2328 2299 2170 2276 2164 1985 2236 + 2245 2137 1972 2182 1902 2327 2130 2046 2237 2246 2273 2163 2031 2267 1981 + 2073 2057 1955 2224 2130 1673 1669 1563 1658 1645 1853 1785 1729 1714 1988 + 2230 1766 1910 1507 1817 2175 2111 2024 2289 2177 2214 2080 1984 1770 2042 + 2173 2271 2101 689 522 613 514 589 663 9999999 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv170.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv170.atsp new file mode 100644 index 0000000..22a978b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv170.atsp @@ -0,0 +1,4882 @@ +NAME: ftv170 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 171 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 100000000 9 15 19 39 50 + 67 55 75 58 67 85 + 99 100 95 111 125 110 + 103 91 100 109 123 134 + 156 130 143 153 140 126 + 144 132 122 121 111 99 + 112 84 78 88 100 134 + 159 119 125 115 126 137 + 150 51 65 80 91 105 + 148 127 167 180 167 98 + 85 100 188 134 153 132 + 119 117 104 115 140 67 + 47 35 49 68 79 22 + 35 29 22 13 40 82 + 94 133 140 127 141 123 + 130 106 97 85 115 131 + 128 95 114 109 127 143 + 131 143 89 82 74 61 + 67 49 29 21 39 58 + 72 77 90 101 109 127 + 137 136 152 165 111 96 + 85 78 140 131 91 91 + 46 59 69 106 128 138 + 118 132 134 85 86 111 + 122 176 159 128 142 115 + 140 106 91 153 112 127 + 107 114 117 115 123 147 + 158 122 67 109 76 124 + 60 68 45 9 100000000 6 + 26 46 57 74 62 82 + 65 74 76 90 104 102 + 118 132 114 94 82 91 + 100 114 125 147 137 134 + 144 131 117 135 123 113 + 112 102 90 103 75 69 + 79 91 125 150 110 116 + 106 117 128 141 42 56 + 71 82 96 139 118 158 + 171 158 89 76 91 179 + 125 144 123 110 108 95 + 118 131 58 38 26 40 + 59 86 13 26 38 31 + 22 34 91 103 136 143 + 136 150 132 139 115 106 + 94 124 140 137 104 123 + 118 136 152 140 152 98 + 91 83 70 76 58 38 + 30 48 67 81 86 99 + 110 118 136 146 145 161 + 174 120 105 94 87 149 + 140 100 100 55 68 78 + 115 137 147 127 141 141 + 94 93 118 129 185 168 + 135 149 122 147 113 98 + 162 121 118 98 105 108 + 122 130 154 167 131 76 + 118 85 115 51 75 36 + 15 6 100000000 20 40 51 + 68 56 76 59 68 82 + 96 101 96 112 126 111 + 100 88 97 106 120 131 + 153 131 140 150 137 123 + 141 129 119 118 108 96 + 109 81 75 85 97 131 + 156 116 122 112 123 134 + 147 48 62 77 88 102 + 145 124 164 177 164 95 + 82 97 185 131 150 129 + 116 114 101 124 137 64 + 44 32 46 65 80 19 + 32 44 37 28 40 97 + 109 142 149 142 156 138 + 145 121 112 100 130 146 + 143 110 129 124 142 158 + 146 158 104 97 89 76 + 82 64 44 36 54 73 + 87 92 105 116 124 142 + 152 151 167 180 126 111 + 100 93 155 146 106 100 + 61 68 78 121 143 151 + 133 147 135 94 87 112 + 123 191 174 129 143 116 + 141 107 92 168 127 124 + 104 111 114 116 124 148 + 173 137 82 124 91 121 + 57 69 42 75 66 60 + 100000000 20 31 48 36 56 + 39 48 112 126 81 76 + 92 106 91 102 112 118 + 109 123 134 156 111 140 + 153 140 126 144 149 126 + 160 168 156 144 141 135 + 145 157 190 215 176 182 + 172 183 194 207 108 122 + 137 148 162 205 184 224 + 237 224 155 142 157 245 + 190 209 188 175 161 161 + 151 177 124 104 92 76 + 95 60 79 92 104 97 + 88 100 118 130 169 176 + 163 177 159 166 142 133 + 121 151 167 164 131 150 + 145 163 179 167 179 125 + 118 110 97 103 85 65 + 57 75 94 108 113 126 + 137 145 163 173 172 188 + 201 147 132 121 114 160 + 151 127 80 82 48 58 + 142 141 131 148 162 115 + 74 67 92 103 196 179 + 109 123 96 121 87 72 + 189 148 184 164 161 131 + 96 104 128 194 158 103 + 145 112 168 117 49 102 + 55 46 40 53 100000000 11 + 28 16 36 19 28 92 + 106 61 56 72 86 71 + 82 92 98 89 103 114 + 136 91 120 133 120 106 + 124 129 106 140 148 136 + 124 121 115 125 137 170 + 195 156 162 152 163 174 + 187 88 102 117 128 142 + 185 164 204 217 204 135 + 122 137 225 170 189 168 + 155 141 141 131 157 104 + 84 72 56 75 40 59 + 72 84 77 68 80 98 + 110 149 156 143 157 139 + 146 122 113 101 131 147 + 144 111 130 125 143 159 + 147 159 105 98 90 77 + 83 65 45 37 55 74 + 88 93 106 117 125 143 + 153 152 168 181 127 112 + 101 94 140 131 107 60 + 62 28 38 122 121 111 + 128 142 95 54 47 72 + 83 176 159 89 103 76 + 101 67 52 169 128 164 + 144 141 111 76 84 108 + 174 138 83 125 92 148 + 97 29 82 47 56 62 + 42 62 100000000 56 66 86 + 81 90 132 146 111 106 + 122 136 121 132 138 147 + 139 153 164 186 141 170 + 183 170 156 174 179 156 + 168 158 146 159 131 125 + 135 147 181 206 166 172 + 162 173 184 197 98 112 + 127 138 152 195 174 193 + 215 214 145 132 147 223 + 159 178 157 144 130 151 + 120 146 114 94 82 96 + 115 102 69 82 76 69 + 60 87 87 99 138 145 + 132 146 128 135 111 102 + 90 120 136 133 100 119 + 114 132 148 136 148 94 + 87 79 66 72 54 34 + 26 44 63 77 82 95 + 106 114 132 142 141 157 + 170 116 101 90 83 145 + 136 96 49 51 17 27 + 111 133 139 123 137 123 + 43 75 100 111 181 164 + 117 131 104 129 95 80 + 158 117 174 154 161 161 + 126 112 136 163 127 72 + 114 81 137 107 18 92 + 82 73 67 87 72 83 + 100000000 10 30 46 55 119 + 133 55 50 66 80 65 + 76 86 92 83 97 108 + 130 85 114 127 114 100 + 118 123 100 134 155 158 + 118 117 137 147 159 164 + 189 183 184 174 185 196 + 209 115 129 144 155 169 + 212 191 231 244 231 162 + 149 164 252 198 217 196 + 183 181 168 191 204 131 + 111 99 83 102 67 86 + 99 111 104 95 107 164 + 176 209 216 209 223 205 + 212 188 179 167 197 212 + 210 176 195 190 208 224 + 182 194 140 163 156 143 + 149 131 111 103 121 109 + 151 128 141 152 160 178 + 188 187 203 216 162 147 + 136 129 131 122 142 94 + 113 100 72 131 112 102 + 119 133 86 56 38 63 + 74 167 150 80 94 67 + 73 39 24 235 194 176 + 165 135 105 70 56 99 + 209 203 118 190 158 188 + 124 101 109 72 63 57 + 77 62 73 90 100000000 20 + 36 45 109 123 45 40 + 56 70 55 66 76 82 + 73 87 98 120 75 104 + 117 104 90 108 113 90 + 124 145 148 108 107 127 + 137 149 154 179 173 174 + 164 175 186 199 105 119 + 134 145 159 202 181 221 + 234 221 152 139 154 242 + 188 207 186 173 171 158 + 181 194 121 101 89 73 + 92 57 76 89 101 94 + 85 97 154 166 199 206 + 199 213 195 202 178 169 + 157 187 203 200 167 186 + 181 199 215 203 215 161 + 154 146 133 139 121 101 + 93 111 130 144 149 162 + 173 181 199 209 208 224 + 237 183 168 157 150 184 + 175 163 122 118 90 100 + 178 165 155 172 186 139 + 109 91 116 127 220 203 + 133 147 120 96 62 77 + 225 184 166 155 125 95 + 60 79 129 230 194 139 + 181 148 178 114 91 99 + 52 43 37 57 42 53 + 70 58 100000000 16 25 89 + 103 25 20 36 50 35 + 46 56 62 53 67 78 + 100 55 84 97 84 70 + 88 93 70 104 125 128 + 88 87 107 117 129 134 + 159 153 154 144 155 166 + 179 85 99 114 125 139 + 182 161 201 214 201 132 + 119 134 222 168 187 166 + 153 151 138 161 174 101 + 81 69 53 72 37 56 + 69 81 74 65 77 134 + 146 179 186 179 193 175 + 182 158 149 137 167 183 + 180 147 166 161 179 195 + 183 195 141 134 126 113 + 119 101 81 73 91 110 + 124 129 142 153 161 179 + 189 188 204 217 163 148 + 137 130 164 155 143 102 + 98 70 80 158 145 135 + 152 166 119 89 71 96 + 107 200 183 113 127 100 + 76 42 57 205 164 146 + 135 105 75 40 59 109 + 210 174 119 161 128 158 + 94 71 79 36 27 21 + 41 26 37 54 42 62 + 100000000 9 73 87 87 82 + 98 112 97 91 79 88 + 97 111 122 144 117 131 + 141 128 114 132 133 110 + 139 129 117 118 102 96 + 106 118 152 177 137 143 + 133 144 155 168 69 83 + 98 109 123 166 145 185 + 198 185 116 103 118 206 + 152 171 150 137 135 122 + 145 158 85 65 53 37 + 56 21 40 53 65 58 + 49 61 118 130 163 170 + 163 177 159 166 142 133 + 121 151 167 164 131 150 + 145 163 179 167 179 125 + 118 110 97 103 85 65 + 57 75 94 108 113 126 + 137 145 163 173 172 188 + 201 147 132 121 114 166 + 157 127 86 82 54 64 + 142 147 137 154 168 121 + 80 73 98 109 202 185 + 115 129 102 127 93 78 + 189 148 145 125 132 105 + 102 110 134 194 158 103 + 145 112 142 78 55 63 + 188 179 185 205 225 236 + 253 229 249 244 100000000 64 + 78 92 230 149 120 102 + 82 70 79 88 102 113 + 135 146 122 132 119 105 + 123 124 101 133 154 145 + 109 104 124 134 146 163 + 188 188 171 161 172 183 + 196 137 151 166 177 191 + 217 196 236 249 236 184 + 196 211 257 245 251 243 + 230 228 215 238 251 187 + 167 153 28 47 12 166 + 179 198 205 201 187 270 + 268 256 263 265 293 311 + 318 294 285 273 303 319 + 316 283 302 297 315 331 + 319 331 277 270 262 249 + 255 237 217 209 227 246 + 260 265 278 289 297 315 + 325 324 340 353 299 284 + 273 266 310 301 279 279 + 234 247 257 294 291 281 + 298 312 273 254 236 261 + 261 346 329 259 232 205 + 174 208 222 305 300 173 + 153 126 96 153 191 207 + 346 310 255 297 264 235 + 158 254 143 146 137 143 + 163 183 194 211 187 207 + 202 10 100000000 14 28 188 + 107 78 38 18 28 37 + 46 60 71 93 104 80 + 90 77 63 81 82 59 + 91 112 103 67 62 82 + 92 104 121 146 146 129 + 119 130 141 154 95 109 + 124 135 149 175 154 194 + 207 194 142 154 169 215 + 203 209 201 188 186 173 + 196 209 145 125 111 38 + 57 22 124 137 156 163 + 159 145 228 226 214 221 + 223 251 269 276 252 243 + 231 261 277 274 241 260 + 255 273 289 277 289 235 + 228 220 207 213 195 175 + 167 185 204 218 223 236 + 247 255 273 283 282 298 + 311 257 242 231 224 268 + 259 237 237 192 205 215 + 252 249 239 256 270 231 + 212 194 219 219 304 287 + 217 190 163 132 166 180 + 263 258 131 111 84 54 + 111 149 165 304 268 213 + 255 222 193 116 212 101 + 138 129 135 155 175 186 + 203 179 199 194 92 82 + 100000000 14 180 99 70 24 + 10 20 29 38 52 63 + 85 96 72 82 69 55 + 73 74 51 83 104 95 + 59 54 74 84 96 113 + 138 138 121 111 122 133 + 146 87 101 116 127 141 + 167 146 186 199 186 134 + 146 161 207 195 201 193 + 180 178 165 188 201 137 + 117 103 117 65 104 116 + 129 148 155 151 137 220 + 218 206 213 215 243 261 + 268 244 235 223 253 269 + 266 233 252 247 265 281 + 269 281 227 220 212 199 + 205 187 167 159 177 196 + 210 215 228 239 247 265 + 275 274 290 303 249 234 + 223 216 260 251 229 229 + 184 197 207 244 241 231 + 248 262 223 204 186 211 + 211 296 279 209 182 155 + 124 158 172 255 250 123 + 103 76 46 103 141 157 + 296 260 205 247 214 185 + 108 204 93 146 137 143 + 163 183 194 211 169 189 + 202 100 90 104 100000000 170 + 89 60 10 21 31 37 + 28 42 53 75 86 62 + 72 59 45 63 68 45 + 79 100 103 63 62 82 + 92 104 109 134 146 129 + 119 130 141 154 95 109 + 124 135 149 175 154 194 + 207 194 142 154 169 215 + 203 209 201 188 186 173 + 196 209 145 125 111 125 + 73 112 124 137 156 163 + 159 145 228 226 214 221 + 223 251 269 276 252 243 + 231 261 277 274 241 260 + 255 273 289 277 289 235 + 228 220 207 213 195 175 + 167 185 204 218 223 236 + 247 255 273 283 282 298 + 311 257 242 231 224 250 + 241 237 232 192 205 210 + 250 231 221 238 252 213 + 194 176 201 201 286 269 + 199 172 145 114 148 162 + 263 258 121 110 80 50 + 93 131 147 304 268 213 + 255 222 193 116 212 101 + 115 106 100 120 105 116 + 91 43 63 79 88 95 + 109 5 100000000 16 30 15 + 26 36 42 33 47 58 + 80 35 64 77 64 50 + 68 73 50 84 105 108 + 68 67 87 97 109 114 + 139 151 134 124 135 146 + 159 100 114 129 140 154 + 180 159 199 212 199 147 + 159 174 220 208 214 206 + 193 191 178 201 214 150 + 130 116 116 78 100 119 + 132 144 137 128 140 197 + 209 219 226 228 256 238 + 245 221 212 200 230 225 + 238 189 208 203 221 237 + 195 207 153 176 189 176 + 182 164 144 136 154 122 + 164 141 154 165 173 191 + 201 200 216 229 175 160 + 149 142 144 135 155 107 + 126 133 85 144 125 115 + 132 146 99 69 51 76 + 87 180 163 93 107 80 + 56 22 37 268 227 126 + 115 85 55 20 39 89 + 222 216 131 203 191 198 + 121 134 106 164 155 159 + 179 164 175 149 102 122 + 138 118 108 122 20 103 + 100000000 14 28 39 49 55 + 46 60 57 79 19 48 + 61 74 63 81 86 63 + 97 118 121 81 80 100 + 110 122 127 152 164 147 + 137 148 159 172 113 127 + 142 153 167 193 172 212 + 225 212 160 172 187 233 + 221 227 219 206 204 191 + 214 227 163 143 129 143 + 91 130 142 155 174 181 + 177 163 246 244 232 239 + 241 269 287 294 270 261 + 249 279 283 292 247 266 + 261 279 295 253 265 211 + 234 238 225 231 213 193 + 185 203 180 222 199 212 + 223 231 249 247 240 256 + 273 215 218 207 200 183 + 174 198 165 184 192 143 + 183 164 154 171 185 146 + 127 109 134 134 219 202 + 132 105 78 47 81 95 + 281 276 139 128 98 68 + 4 64 80 280 274 189 + 261 240 211 134 193 119 + 150 141 147 167 187 198 + 215 173 193 206 104 94 + 108 113 174 93 100000000 14 + 25 35 41 32 46 57 + 79 90 66 76 63 49 + 67 72 49 83 104 107 + 67 66 86 96 108 113 + 138 150 133 123 134 145 + 158 99 113 128 139 153 + 179 158 198 211 198 146 + 158 173 219 207 213 205 + 192 190 177 200 213 149 + 129 115 129 77 116 128 + 141 160 167 163 149 232 + 230 218 225 227 255 273 + 280 256 247 235 265 281 + 278 245 264 259 277 293 + 281 293 239 232 224 211 + 217 199 179 171 189 208 + 222 227 240 251 259 277 + 287 286 302 315 261 246 + 235 228 254 245 241 236 + 196 209 214 254 235 225 + 242 256 217 198 180 205 + 205 290 273 203 176 149 + 118 152 166 267 262 125 + 114 84 54 97 135 151 + 308 272 217 259 226 197 + 120 216 105 136 127 133 + 153 173 184 201 159 179 + 192 90 80 94 99 160 + 79 50 100000000 11 21 27 + 18 32 43 65 76 52 + 62 49 35 53 58 35 + 69 90 93 53 52 72 + 82 94 99 124 136 119 + 109 120 131 144 85 99 + 114 125 139 165 144 184 + 197 184 132 144 159 205 + 193 199 191 178 176 163 + 186 199 135 115 101 115 + 63 102 114 127 146 153 + 149 135 218 216 204 211 + 213 241 259 266 242 233 + 221 251 267 264 231 250 + 245 263 279 267 279 225 + 218 210 197 203 185 165 + 157 175 194 208 213 226 + 237 245 263 273 272 288 + 301 247 232 221 214 240 + 231 227 222 182 195 200 + 240 221 211 228 242 203 + 184 166 191 191 276 259 + 189 162 135 104 138 152 + 253 248 111 100 70 40 + 83 121 137 294 258 203 + 245 212 183 106 202 91 + 128 119 125 145 165 176 + 193 169 189 184 82 72 + 86 100 170 89 60 46 + 100000000 10 19 28 42 53 + 75 86 62 72 59 45 + 63 64 41 73 94 85 + 49 44 64 74 86 103 + 128 128 111 101 112 123 + 136 77 91 106 117 131 + 157 136 176 189 176 124 + 136 151 197 185 191 183 + 170 168 155 178 191 127 + 107 93 107 55 94 106 + 119 138 145 141 127 210 + 208 196 203 205 233 251 + 258 234 225 213 243 259 + 256 223 242 237 255 271 + 259 271 217 210 202 189 + 195 177 157 149 167 186 + 200 205 218 229 237 255 + 265 264 280 293 239 224 + 213 206 250 241 219 219 + 174 187 197 234 231 221 + 238 252 213 194 176 201 + 201 286 269 199 172 145 + 114 148 162 245 240 113 + 93 66 36 93 131 147 + 286 250 195 237 204 175 + 98 194 83 118 109 115 + 135 155 166 183 159 179 + 174 72 62 76 90 160 + 79 50 36 47 100000000 9 + 18 32 43 65 76 52 + 62 49 35 53 54 31 + 63 84 75 39 34 54 + 64 76 93 118 118 101 + 91 102 113 126 67 81 + 96 107 121 147 126 166 + 179 166 114 126 141 187 + 175 181 173 160 158 145 + 168 181 117 97 83 97 + 45 84 96 109 128 135 + 131 117 200 198 186 193 + 195 223 241 248 224 215 + 203 233 249 246 213 232 + 227 245 261 249 261 207 + 200 192 179 185 167 147 + 139 157 176 190 195 208 + 219 227 245 255 254 270 + 283 229 214 203 196 240 + 231 209 209 164 177 187 + 224 221 211 228 242 203 + 184 166 191 191 276 259 + 189 162 135 104 138 152 + 235 230 103 83 56 26 + 83 121 137 276 240 185 + 227 194 165 88 184 73 + 109 100 106 126 146 157 + 174 150 170 165 63 53 + 67 81 151 70 41 27 + 38 48 100000000 9 23 34 + 56 67 43 53 40 26 + 44 45 22 54 75 66 + 30 25 45 55 67 84 + 109 109 92 82 93 104 + 117 58 72 87 98 112 + 138 117 157 170 157 105 + 117 132 178 166 172 164 + 151 149 136 159 172 108 + 88 74 88 36 75 87 + 100 119 126 122 108 191 + 189 177 184 186 214 232 + 239 215 206 194 224 240 + 237 204 223 218 236 252 + 240 252 198 191 183 170 + 176 158 138 130 148 167 + 181 186 199 210 218 236 + 246 245 261 274 220 205 + 194 187 231 222 200 200 + 155 168 178 215 212 202 + 219 233 194 175 157 182 + 182 267 250 180 153 126 + 95 129 143 226 221 94 + 74 47 17 74 112 128 + 267 231 176 218 185 156 + 79 175 64 118 109 115 + 135 155 166 183 141 161 + 174 72 62 76 81 142 + 61 32 18 29 39 9 + 100000000 14 25 47 58 34 + 44 31 17 35 40 17 + 51 72 75 35 34 54 + 64 76 81 106 118 101 + 91 102 113 126 67 81 + 96 107 121 147 126 166 + 179 166 114 126 141 187 + 175 181 173 160 158 145 + 168 181 117 97 83 97 + 45 84 96 109 128 135 + 131 117 200 198 186 193 + 195 223 241 248 224 215 + 203 233 249 246 213 232 + 227 245 261 249 261 207 + 200 192 179 185 167 147 + 139 157 176 190 195 208 + 219 227 245 255 254 270 + 283 229 214 203 196 222 + 213 209 204 164 177 182 + 222 203 193 210 224 185 + 166 148 173 173 258 241 + 171 144 117 86 120 134 + 235 230 93 82 52 22 + 65 103 119 276 240 185 + 227 194 165 88 184 73 + 132 123 129 149 169 180 + 174 127 147 163 86 76 + 90 67 128 47 18 32 + 43 53 23 14 100000000 11 + 33 44 20 33 45 31 + 49 54 31 65 86 89 + 49 48 68 78 90 95 + 120 132 115 105 116 127 + 140 81 95 110 121 135 + 161 140 180 193 180 128 + 140 155 201 189 195 187 + 174 172 159 182 195 131 + 111 97 111 59 98 110 + 123 142 149 145 131 214 + 212 200 207 209 237 255 + 262 238 229 217 247 263 + 260 227 246 241 259 275 + 263 275 221 214 206 193 + 199 181 161 153 171 190 + 204 209 222 233 241 259 + 269 265 281 297 240 228 + 217 210 208 199 223 190 + 178 191 168 208 189 179 + 196 210 171 152 134 159 + 159 244 227 157 130 103 + 72 106 120 249 244 107 + 96 66 36 51 89 105 + 290 254 199 241 208 179 + 102 198 87 143 134 140 + 160 178 189 163 116 136 + 152 97 87 101 56 117 + 36 29 43 54 64 34 + 25 11 100000000 22 33 9 + 22 35 42 50 65 42 + 76 97 100 60 59 79 + 89 101 106 131 143 126 + 116 127 138 151 92 106 + 121 132 146 172 151 191 + 204 191 139 151 166 212 + 200 206 198 185 183 170 + 193 206 142 122 108 122 + 70 109 121 134 153 160 + 156 142 225 223 211 218 + 220 248 266 273 249 240 + 228 258 274 271 238 257 + 252 270 286 267 279 225 + 225 217 204 210 192 172 + 164 182 194 215 213 226 + 237 245 263 261 254 270 + 287 229 232 221 214 197 + 188 212 179 189 202 157 + 197 178 168 185 199 160 + 141 123 148 148 233 216 + 146 119 92 61 95 109 + 260 255 118 107 77 47 + 40 78 94 294 265 203 + 252 219 190 113 207 98 + 166 157 151 171 156 167 + 141 94 114 130 132 122 + 136 34 95 14 28 42 + 53 63 69 60 60 49 + 100000000 11 40 53 66 77 + 81 98 77 109 130 135 + 95 94 114 124 136 139 + 164 178 161 151 162 173 + 186 127 141 156 167 181 + 207 186 226 239 226 174 + 186 201 247 235 241 233 + 220 218 205 228 241 177 + 157 143 157 105 144 156 + 169 188 188 179 177 248 + 258 246 253 255 283 289 + 296 272 263 251 281 275 + 288 239 258 253 271 287 + 245 257 203 226 240 227 + 233 215 195 187 205 172 + 214 191 204 215 223 241 + 239 232 248 265 207 210 + 199 192 175 166 190 157 + 176 184 135 175 156 146 + 163 177 138 119 101 126 + 126 211 194 124 97 70 + 39 73 87 295 278 151 + 140 112 82 18 56 72 + 272 266 181 253 242 225 + 148 185 133 155 146 140 + 160 145 156 130 83 103 + 119 128 125 139 89 84 + 74 67 81 92 102 72 + 63 49 38 60 100000000 29 + 42 55 69 70 87 80 + 98 119 131 98 97 117 + 127 136 128 153 178 161 + 151 162 173 186 130 144 + 159 170 184 207 186 226 + 239 226 177 189 204 247 + 238 241 236 223 221 208 + 231 244 180 160 146 156 + 108 140 159 172 184 177 + 168 180 237 249 249 256 + 258 286 278 285 261 252 + 240 270 264 277 228 247 + 242 260 276 234 246 192 + 215 229 216 222 204 184 + 176 194 161 203 180 193 + 204 212 230 228 221 237 + 254 196 199 188 181 164 + 155 179 146 165 173 124 + 164 145 135 152 166 127 + 108 90 115 115 200 183 + 113 86 59 28 62 76 + 298 267 140 129 115 85 + 78 45 61 261 255 170 + 242 231 228 151 174 136 + 152 143 149 169 174 185 + 159 112 132 148 106 96 + 110 65 113 45 38 52 + 63 73 43 34 20 9 + 31 29 100000000 13 26 40 + 41 58 51 69 90 102 + 69 68 88 98 107 99 + 124 149 132 122 133 144 + 157 101 115 130 141 155 + 178 157 197 210 197 148 + 160 175 218 209 212 207 + 194 192 179 202 215 151 + 131 117 131 79 118 130 + 143 162 169 165 151 234 + 232 220 227 229 257 275 + 282 258 249 237 267 283 + 280 247 266 261 279 295 + 263 275 221 234 226 213 + 219 201 181 173 191 190 + 224 209 222 233 241 259 + 257 250 266 283 225 228 + 217 210 193 184 208 175 + 194 202 153 193 174 164 + 181 195 156 137 119 144 + 144 229 212 142 115 88 + 57 91 105 269 264 111 + 100 86 56 49 74 90 + 290 274 199 261 228 199 + 122 203 107 162 153 159 + 179 187 198 172 125 145 + 161 116 106 120 78 126 + 58 51 62 73 83 53 + 44 33 22 44 42 13 + 100000000 13 27 28 45 61 + 56 77 89 79 78 98 + 106 94 86 111 136 119 + 109 120 131 144 111 125 + 140 147 161 165 144 184 + 197 184 158 170 185 205 + 219 199 217 204 202 189 + 212 225 161 141 127 141 + 89 128 140 153 172 179 + 175 161 244 242 230 237 + 239 267 285 292 268 259 + 247 277 293 290 257 276 + 271 289 305 276 288 234 + 244 236 223 229 211 191 + 183 201 203 234 222 235 + 246 254 272 270 263 279 + 296 238 241 230 223 206 + 197 221 188 207 215 166 + 206 187 177 194 208 169 + 150 132 157 157 242 225 + 155 128 101 70 104 118 + 279 274 98 87 96 66 + 62 87 103 303 284 212 + 271 238 209 132 216 117 + 149 140 146 166 186 197 + 185 138 158 174 103 93 + 107 78 139 58 43 49 + 60 70 40 31 25 22 + 44 55 26 13 100000000 14 + 15 32 48 43 64 76 + 66 65 85 93 81 73 + 98 123 106 96 107 118 + 131 98 112 127 134 148 + 152 131 171 184 171 145 + 157 172 192 206 186 204 + 191 189 176 199 212 148 + 128 114 128 76 115 127 + 140 159 166 162 148 231 + 229 217 224 226 254 272 + 279 255 246 234 264 280 + 277 244 263 258 276 292 + 280 292 238 231 223 210 + 216 198 178 170 188 207 + 221 226 239 250 258 276 + 283 276 292 309 251 245 + 234 227 219 210 234 201 + 195 208 179 219 200 190 + 207 221 182 163 145 170 + 170 255 238 168 141 114 + 83 117 131 266 261 85 + 74 83 53 62 100 116 + 307 271 216 258 225 196 + 119 215 104 135 126 132 + 152 172 183 185 138 158 + 174 89 79 93 78 139 + 58 29 35 46 56 26 + 17 11 22 44 55 31 + 27 14 100000000 18 35 34 + 46 67 79 52 51 71 + 81 84 76 101 126 109 + 99 110 121 134 84 98 + 113 124 138 155 134 174 + 187 174 131 143 158 195 + 192 189 190 177 175 162 + 185 198 134 114 100 114 + 62 101 113 126 145 152 + 148 134 217 215 203 210 + 212 240 258 265 241 232 + 220 250 266 263 230 249 + 244 262 278 266 278 224 + 217 209 196 202 184 164 + 156 174 193 207 212 225 + 236 244 262 272 271 287 + 300 246 231 220 213 219 + 210 226 201 181 194 179 + 219 200 190 207 221 182 + 163 145 170 170 255 238 + 168 141 114 83 117 131 + 252 247 88 77 69 39 + 62 100 116 293 257 202 + 244 211 182 105 201 90 + 164 155 161 181 201 212 + 200 153 173 189 118 108 + 122 93 154 73 58 64 + 75 85 55 46 40 37 + 59 70 41 28 15 29 + 100000000 17 40 28 49 61 + 58 80 88 78 66 58 + 83 108 91 81 92 103 + 116 113 127 127 119 133 + 137 116 156 169 156 145 + 157 172 177 202 171 203 + 191 189 176 199 212 163 + 143 129 143 91 130 142 + 155 174 181 177 163 239 + 229 217 224 226 253 271 + 278 257 248 241 266 295 + 279 259 278 273 291 307 + 295 307 253 246 238 225 + 231 213 193 185 203 222 + 236 241 254 265 273 291 + 298 291 307 324 266 260 + 249 242 234 225 249 216 + 210 223 194 234 215 205 + 222 236 197 178 160 185 + 185 270 253 183 156 129 + 98 132 146 265 263 70 + 59 75 45 77 115 131 + 322 286 231 273 240 196 + 134 230 119 154 145 151 + 171 191 202 217 170 190 + 206 108 98 112 110 171 + 90 72 58 69 79 49 + 40 54 54 76 87 58 + 45 32 46 17 100000000 23 + 11 32 44 41 70 71 + 61 49 41 66 91 74 + 64 75 86 99 103 117 + 110 102 116 120 99 139 + 152 139 128 140 155 160 + 185 154 186 174 172 159 + 182 195 153 133 119 133 + 81 120 132 145 164 171 + 167 153 222 212 200 207 + 209 236 254 261 240 231 + 224 249 285 262 249 268 + 263 281 297 285 297 243 + 236 228 215 221 203 183 + 175 193 212 226 231 244 + 255 263 281 291 290 306 + 319 265 250 239 232 251 + 242 245 233 200 213 211 + 251 232 222 239 253 214 + 195 177 202 202 287 270 + 200 173 146 115 149 163 + 248 246 53 42 58 28 + 94 132 148 312 276 221 + 263 230 179 124 220 109 + 131 122 128 148 168 179 + 196 158 178 187 85 75 + 89 98 159 78 49 35 + 46 56 26 17 31 42 + 64 75 51 61 48 34 + 40 23 100000000 34 55 67 + 18 47 67 77 72 64 + 89 114 97 87 98 109 + 122 80 94 109 120 134 + 143 122 162 175 162 127 + 139 154 183 188 177 186 + 173 171 158 181 194 130 + 110 96 110 58 97 109 + 122 141 148 144 130 213 + 211 199 206 208 236 254 + 261 237 228 216 246 262 + 259 226 245 240 258 274 + 262 274 220 213 205 192 + 198 180 160 152 170 189 + 203 208 221 232 240 258 + 268 267 283 296 242 227 + 216 209 239 230 222 221 + 177 190 199 237 220 210 + 227 241 202 183 165 190 + 190 275 258 188 161 134 + 103 137 151 248 243 76 + 65 35 5 82 120 136 + 289 253 198 240 207 178 + 101 197 86 152 143 149 + 169 189 200 217 181 201 + 208 113 103 117 121 182 + 101 83 69 80 90 60 + 51 65 65 87 98 69 + 56 43 57 28 11 34 + 100000000 21 33 46 75 60 + 50 38 30 55 80 63 + 53 64 75 88 101 115 + 99 91 105 109 88 128 + 141 128 117 129 144 149 + 174 143 175 163 161 148 + 171 184 151 131 117 131 + 86 125 130 143 162 169 + 165 151 211 201 189 196 + 198 225 243 250 229 220 + 213 238 283 251 247 266 + 261 279 295 283 295 241 + 234 226 213 219 201 181 + 173 191 210 224 229 242 + 253 261 279 289 288 304 + 317 263 248 237 230 262 + 253 243 243 198 211 221 + 258 243 233 250 264 225 + 206 188 213 213 298 281 + 211 184 157 126 160 174 + 237 235 42 31 48 39 + 105 143 159 310 274 219 + 261 222 168 122 218 107 + 131 122 128 148 168 179 + 196 184 204 187 92 82 + 96 110 203 122 104 90 + 100 88 79 72 86 86 + 108 119 90 77 64 78 + 49 32 55 21 100000000 12 + 25 54 39 29 17 23 + 48 59 42 32 43 54 + 67 80 94 78 70 84 + 88 67 107 120 107 96 + 108 123 128 153 122 154 + 142 140 127 150 163 130 + 110 96 110 65 104 109 + 122 141 148 144 130 190 + 180 168 175 177 204 222 + 229 208 199 192 217 262 + 230 226 245 240 258 274 + 262 274 220 213 205 192 + 198 180 160 152 170 189 + 203 208 221 232 240 258 + 268 267 283 296 242 227 + 216 209 271 262 222 222 + 177 190 200 237 259 254 + 249 263 246 216 209 234 + 234 307 290 232 205 178 + 147 181 195 216 214 30 + 10 27 60 126 164 180 + 289 253 198 240 201 147 + 101 197 86 126 117 123 + 143 163 174 191 179 199 + 182 80 70 84 98 204 + 123 105 91 88 76 67 + 73 87 87 109 120 91 + 78 65 79 50 33 56 + 22 12 100000000 13 42 51 + 41 29 35 60 71 54 + 44 55 66 79 75 89 + 90 82 96 100 79 119 + 132 119 108 120 135 140 + 165 134 166 154 152 139 + 162 175 125 105 91 105 + 53 92 104 117 136 143 + 139 125 202 192 180 187 + 189 216 234 241 220 211 + 204 229 257 242 221 240 + 235 253 269 257 269 215 + 208 200 187 193 175 155 + 147 165 184 198 203 216 + 227 235 253 263 262 278 + 291 237 222 211 204 266 + 257 217 217 172 185 195 + 232 254 255 244 258 247 + 211 210 235 235 302 285 + 233 206 179 148 182 196 + 228 226 42 22 15 61 + 127 165 181 284 248 193 + 235 202 159 96 192 81 + 113 104 110 130 150 161 + 178 166 186 169 67 57 + 71 85 192 111 93 79 + 75 63 54 61 75 75 + 97 108 79 66 53 67 + 38 21 44 24 45 57 + 100000000 29 49 59 62 54 + 79 104 87 77 88 99 + 112 62 76 91 102 116 + 133 112 152 165 152 109 + 121 136 173 170 167 168 + 155 153 140 163 176 112 + 92 78 92 40 79 91 + 104 123 130 126 112 195 + 193 181 188 190 218 236 + 243 219 210 198 228 244 + 241 208 227 222 240 256 + 244 256 202 195 187 174 + 180 162 142 134 152 171 + 185 190 203 214 222 240 + 250 249 265 278 224 209 + 198 191 253 244 204 204 + 159 172 182 219 241 243 + 231 245 235 198 197 222 + 223 289 272 221 194 167 + 136 170 184 230 225 66 + 55 17 49 115 153 169 + 271 235 180 222 189 160 + 83 179 68 84 75 81 + 101 121 132 149 137 157 + 140 38 28 42 56 176 + 95 66 52 46 34 25 + 34 48 59 81 92 68 + 78 65 51 69 70 47 + 63 53 41 54 100000000 20 + 30 42 76 101 84 67 + 57 68 79 92 33 47 + 62 73 87 113 92 132 + 145 132 80 92 107 153 + 141 147 139 126 124 111 + 134 147 83 63 49 63 + 11 50 62 75 94 101 + 97 83 166 164 152 159 + 161 189 207 214 190 181 + 169 199 215 212 179 198 + 193 211 227 215 227 173 + 166 158 145 151 133 113 + 105 123 142 156 161 174 + 185 193 211 221 220 236 + 249 195 180 169 162 224 + 215 175 175 130 143 153 + 190 212 222 202 216 216 + 169 168 193 204 260 243 + 205 178 151 120 154 168 + 201 196 69 49 56 42 + 99 137 153 242 206 151 + 193 160 131 54 150 39 + 104 95 101 121 141 152 + 169 157 177 160 58 48 + 62 76 196 115 86 72 + 66 54 45 54 68 79 + 101 112 88 98 85 71 + 71 54 67 43 33 21 + 34 20 100000000 10 22 56 + 81 64 47 37 48 59 + 72 53 67 82 75 89 + 93 72 112 125 112 100 + 112 127 133 158 127 159 + 146 144 131 154 167 103 + 83 69 83 31 70 82 + 95 114 121 117 103 186 + 184 172 179 181 209 227 + 234 210 201 189 219 235 + 232 199 218 213 231 247 + 235 247 193 186 178 165 + 171 153 133 125 143 162 + 176 181 194 205 213 231 + 241 240 256 269 215 200 + 189 182 244 235 195 195 + 150 163 173 210 232 242 + 222 236 236 189 188 213 + 224 280 263 225 198 171 + 140 174 188 221 216 49 + 29 36 62 119 157 173 + 262 226 171 213 180 151 + 74 170 59 114 105 111 + 131 151 162 179 167 187 + 170 68 58 72 86 206 + 125 96 82 76 64 55 + 64 78 89 111 122 98 + 106 93 81 78 61 77 + 50 29 31 44 30 10 + 100000000 12 51 76 54 37 + 27 38 49 62 63 77 + 73 65 79 83 62 102 + 115 102 91 103 118 123 + 148 117 149 137 135 122 + 145 158 113 93 79 93 + 41 80 92 105 124 131 + 127 113 185 175 163 170 + 172 199 217 224 203 194 + 187 212 245 225 209 228 + 223 241 257 245 257 203 + 196 188 175 181 163 143 + 135 153 172 186 191 204 + 215 223 241 251 250 266 + 279 225 210 199 192 254 + 245 205 205 160 173 183 + 220 242 252 232 246 246 + 199 198 223 234 290 273 + 235 208 181 150 184 198 + 211 209 39 19 46 72 + 129 167 183 272 236 181 + 223 190 142 84 180 69 + 114 105 111 131 151 162 + 179 167 187 170 80 70 + 84 98 207 137 108 94 + 88 76 67 76 90 101 + 123 134 107 94 81 93 + 66 49 72 38 17 29 + 42 42 22 12 100000000 39 + 64 42 25 15 26 37 + 50 63 77 61 53 67 + 71 50 90 103 90 79 + 91 106 111 136 105 137 + 125 123 110 133 146 113 + 93 79 93 53 92 92 + 105 124 131 127 113 173 + 163 151 158 160 187 205 + 212 191 182 175 200 245 + 213 209 228 223 241 257 + 245 257 203 196 188 175 + 181 163 143 135 153 172 + 186 191 204 215 223 241 + 251 250 266 279 225 210 + 199 192 254 245 205 205 + 160 173 183 220 242 252 + 232 246 246 199 198 223 + 234 290 273 240 220 193 + 162 196 203 199 197 27 + 7 44 77 141 179 195 + 272 236 181 223 184 130 + 84 180 69 153 144 150 + 170 190 201 218 206 226 + 209 115 105 119 133 212 + 131 113 99 110 111 90 + 81 95 95 117 128 99 + 86 73 87 58 41 64 + 30 23 35 48 77 61 + 51 39 100000000 25 81 64 + 54 65 76 89 102 116 + 100 92 94 85 64 104 + 117 104 113 125 140 125 + 150 119 151 159 157 144 + 167 180 152 132 118 132 + 88 127 131 144 163 170 + 166 152 207 197 185 192 + 194 201 219 226 225 216 + 209 234 282 247 248 265 + 262 280 296 284 296 242 + 235 227 214 220 202 182 + 174 192 211 225 230 243 + 254 262 280 290 289 305 + 318 264 249 238 231 292 + 283 244 244 199 212 222 + 259 273 263 271 285 255 + 236 218 243 243 328 311 + 241 214 187 156 190 204 + 213 231 12 32 50 69 + 135 173 189 311 275 220 + 262 218 164 123 219 108 + 133 124 130 150 170 181 + 198 186 206 189 129 119 + 133 147 226 156 138 124 + 135 125 115 106 120 120 + 142 153 124 111 98 112 + 83 66 89 55 48 60 + 73 91 71 61 49 25 + 100000000 61 44 34 45 56 + 69 82 96 80 72 69 + 60 39 79 92 79 88 + 100 115 100 125 94 126 + 134 132 119 142 155 132 + 112 98 112 102 141 111 + 124 143 150 146 132 182 + 172 160 167 169 176 194 + 201 200 191 184 209 257 + 222 228 240 242 260 276 + 264 276 222 215 207 194 + 200 182 162 154 172 191 + 205 210 223 234 242 260 + 270 269 285 298 244 229 + 218 211 273 264 224 224 + 179 192 202 239 261 271 + 251 265 265 218 217 242 + 253 309 292 259 239 212 + 181 215 222 188 206 37 + 56 75 94 160 198 214 + 291 255 200 242 193 139 + 103 199 88 129 120 126 + 146 166 177 194 182 202 + 185 125 115 129 143 222 + 182 153 139 133 121 112 + 121 135 146 168 179 152 + 139 126 138 111 94 117 + 83 62 74 87 87 67 + 57 45 72 47 100000000 20 + 30 41 52 65 78 84 + 76 68 38 29 8 48 + 61 48 57 69 84 69 + 94 63 95 103 101 88 + 111 124 128 108 94 108 + 98 137 107 120 139 146 + 142 128 151 141 129 136 + 138 145 163 170 169 160 + 153 178 226 191 201 209 + 215 233 246 247 259 218 + 204 196 183 171 178 158 + 150 168 187 201 206 219 + 230 238 256 266 265 281 + 268 240 225 214 207 269 + 260 220 220 175 188 198 + 235 257 267 247 261 261 + 214 213 238 249 305 288 + 255 265 238 207 233 218 + 157 175 72 52 89 122 + 186 224 240 274 228 196 + 215 162 108 99 195 84 + 109 100 106 126 146 157 + 174 162 182 165 105 95 + 109 123 202 162 133 119 + 113 101 92 101 115 126 + 148 159 132 119 106 118 + 91 74 97 63 42 54 + 67 67 47 37 25 64 + 84 37 100000000 10 21 32 + 45 58 72 56 48 62 + 66 45 85 98 85 74 + 86 101 106 131 100 132 + 120 118 105 128 141 108 + 88 74 88 78 117 87 + 100 119 126 122 108 168 + 158 146 153 155 182 200 + 207 186 177 170 195 240 + 208 204 223 218 236 252 + 240 252 198 191 183 170 + 176 158 138 130 148 167 + 181 186 199 210 218 236 + 246 245 261 274 220 205 + 194 187 249 240 200 200 + 155 168 178 215 237 247 + 227 241 241 194 193 218 + 229 285 268 235 245 218 + 187 213 198 194 192 52 + 32 69 102 166 204 220 + 267 231 176 218 179 125 + 79 175 64 99 90 96 + 116 136 147 164 152 172 + 155 95 85 99 113 192 + 152 123 109 103 91 82 + 91 105 116 138 149 122 + 109 96 108 81 64 87 + 53 32 44 57 57 37 + 27 15 54 74 27 10 + 100000000 11 22 35 48 62 + 46 38 52 56 35 75 + 88 75 64 76 91 96 + 121 90 122 110 108 95 + 118 131 98 78 64 78 + 68 107 77 90 109 116 + 112 98 158 148 136 143 + 145 172 190 197 176 167 + 160 185 230 198 194 213 + 208 226 242 230 242 188 + 181 173 160 166 148 128 + 120 138 157 171 176 189 + 200 208 226 236 235 251 + 264 210 195 184 177 239 + 230 190 190 145 158 168 + 205 227 237 217 231 231 + 184 183 208 219 275 258 + 225 235 208 177 203 188 + 184 182 42 22 59 92 + 156 194 210 257 221 166 + 208 169 115 69 165 54 + 88 79 85 105 125 136 + 153 141 161 144 95 85 + 99 113 181 152 123 109 + 103 91 82 91 105 116 + 138 149 125 133 120 108 + 105 88 104 77 56 58 + 71 57 37 27 39 78 + 102 55 64 54 100000000 11 + 24 37 51 35 27 41 + 84 63 103 116 103 53 + 65 80 124 114 118 112 + 99 97 84 107 120 87 + 67 53 67 68 107 66 + 79 98 105 101 87 147 + 137 125 132 134 162 180 + 187 165 156 149 174 219 + 187 183 202 197 215 231 + 219 231 177 170 162 149 + 155 137 117 109 127 146 + 160 165 178 189 197 215 + 225 224 240 253 199 184 + 173 166 228 219 179 179 + 134 147 157 194 216 226 + 206 220 220 173 172 197 + 208 264 247 214 228 201 + 177 192 177 174 171 66 + 46 73 99 156 194 210 + 246 210 155 197 158 104 + 58 154 43 77 68 74 + 94 114 125 142 130 150 + 133 84 74 88 102 170 + 141 112 98 92 80 71 + 80 94 105 127 138 114 + 122 109 97 94 77 93 + 66 45 47 60 46 26 + 16 28 67 91 44 53 + 43 51 100000000 13 26 40 + 24 16 30 73 52 92 + 105 92 42 54 69 113 + 103 107 101 88 86 73 + 96 109 76 56 42 56 + 57 96 55 68 87 94 + 90 76 136 126 114 121 + 123 151 169 176 154 145 + 138 163 208 176 172 191 + 186 204 220 208 220 166 + 159 151 138 144 126 106 + 98 116 135 149 154 167 + 178 186 204 214 213 229 + 242 188 173 162 155 217 + 208 168 168 123 136 146 + 183 205 215 195 209 209 + 162 161 186 197 253 236 + 203 217 190 166 181 166 + 163 160 55 35 62 88 + 145 183 199 235 199 144 + 186 147 93 47 143 32 + 64 55 61 81 101 112 + 129 117 137 120 84 74 + 88 102 157 141 112 98 + 92 80 71 80 94 105 + 127 138 114 124 111 97 + 111 94 93 83 73 61 + 74 46 40 50 62 96 + 97 50 70 77 57 68 + 100000000 13 27 11 22 36 + 79 58 98 111 98 29 + 41 56 119 90 109 88 + 75 73 60 83 96 63 + 43 29 43 57 96 42 + 55 74 81 77 63 123 + 113 101 108 110 138 156 + 163 141 132 125 150 195 + 163 159 178 173 191 207 + 195 207 153 146 138 125 + 131 113 93 85 103 122 + 136 141 154 165 173 191 + 201 200 216 229 175 160 + 149 142 204 195 155 155 + 110 123 133 170 192 202 + 182 196 196 149 148 173 + 184 240 223 190 204 177 + 166 168 153 150 147 89 + 69 76 88 145 183 199 + 222 186 131 173 134 80 + 34 130 19 51 42 48 + 68 88 99 116 104 124 + 107 71 61 75 89 144 + 128 99 85 79 67 58 + 67 81 92 114 125 101 + 111 98 84 98 81 80 + 70 60 48 61 33 27 + 37 49 83 108 68 74 + 64 75 86 99 100000000 14 + 29 40 54 97 76 116 + 129 116 47 59 74 137 + 108 127 106 93 91 78 + 101 114 50 30 16 30 + 44 83 29 42 61 68 + 64 50 133 131 119 126 + 128 156 174 181 157 148 + 136 166 182 179 146 165 + 160 178 194 182 194 140 + 133 125 112 118 100 80 + 72 90 109 123 128 141 + 152 160 178 188 187 203 + 216 162 147 136 129 191 + 182 142 142 97 110 120 + 157 179 189 169 183 183 + 136 135 160 171 227 210 + 177 191 164 153 155 140 + 168 163 76 56 63 75 + 132 170 186 209 173 118 + 160 127 98 21 117 6 + 65 56 62 82 102 113 + 130 118 138 121 85 75 + 89 103 158 142 113 99 + 93 81 72 81 95 106 + 128 139 115 125 112 98 + 112 95 94 84 74 62 + 75 47 41 51 63 97 + 101 54 74 78 61 72 + 85 14 100000000 15 26 40 + 83 62 102 115 102 33 + 45 60 123 94 113 92 + 79 77 64 87 100 64 + 44 30 44 58 97 43 + 56 75 82 78 64 127 + 117 105 112 114 142 160 + 167 145 136 129 154 196 + 167 160 179 174 192 208 + 196 208 154 147 139 126 + 132 114 94 86 104 123 + 137 142 155 166 174 192 + 202 201 217 230 176 161 + 150 143 205 196 156 156 + 111 124 134 171 193 203 + 183 197 197 150 149 174 + 185 241 224 191 205 178 + 167 169 154 154 151 90 + 70 77 89 146 184 200 + 223 187 132 174 138 84 + 35 131 20 110 101 107 + 127 147 158 175 163 183 + 166 130 120 134 148 203 + 187 158 144 138 126 117 + 126 140 151 173 184 160 + 170 157 143 150 133 139 + 122 101 104 117 92 83 + 73 84 111 86 39 59 + 69 46 57 70 59 45 + 100000000 11 25 68 47 87 + 100 87 18 30 45 108 + 79 98 77 64 62 49 + 72 85 109 89 75 89 + 103 142 88 101 120 127 + 123 109 112 102 90 97 + 99 127 145 152 130 121 + 114 139 198 152 162 181 + 176 194 210 208 220 193 + 165 157 144 132 159 139 + 131 149 168 182 187 200 + 211 219 237 235 242 249 + 232 221 206 195 188 250 + 241 201 201 156 169 179 + 216 238 248 228 242 242 + 195 194 219 230 286 269 + 236 250 223 212 214 199 + 139 136 111 91 119 134 + 191 229 245 235 189 177 + 176 123 69 80 176 65 + 123 114 120 140 160 171 + 188 176 196 179 130 120 + 134 148 216 187 158 144 + 138 126 117 126 140 151 + 173 184 160 167 154 143 + 139 122 139 111 90 93 + 106 92 72 62 73 100 + 75 28 48 58 35 46 + 59 72 86 70 100000000 14 + 57 36 76 89 76 85 + 97 112 97 122 91 123 + 131 129 116 139 152 122 + 102 88 102 103 142 101 + 114 133 140 136 122 179 + 169 157 164 166 173 191 + 198 197 188 181 206 254 + 219 218 237 232 250 266 + 254 266 212 205 197 184 + 190 172 152 144 162 181 + 195 200 213 224 232 250 + 260 259 275 288 234 219 + 208 201 263 254 214 214 + 169 182 192 229 251 261 + 241 255 255 208 207 232 + 243 299 282 249 263 236 + 212 227 212 185 203 100 + 80 108 134 191 229 245 + 281 245 190 232 190 136 + 93 189 78 109 100 106 + 126 146 157 174 162 182 + 165 116 106 120 134 202 + 173 144 130 124 112 103 + 112 126 137 159 170 146 + 153 140 129 125 108 125 + 97 76 79 92 78 58 + 48 59 86 61 14 34 + 44 21 32 45 58 72 + 56 48 100000000 43 22 62 + 75 62 71 83 98 83 + 108 77 109 117 115 102 + 125 138 108 88 74 88 + 89 128 87 100 119 126 + 122 108 165 155 143 150 + 152 159 177 184 183 174 + 167 192 240 205 204 223 + 218 236 252 240 252 198 + 191 183 170 176 158 138 + 130 148 167 181 186 199 + 210 218 236 246 245 261 + 274 220 205 194 187 249 + 240 200 200 155 168 178 + 215 237 247 227 241 241 + 194 193 218 229 285 268 + 235 249 222 198 213 198 + 171 189 86 66 94 120 + 177 215 231 267 231 176 + 218 176 122 79 175 64 + 118 109 115 135 155 166 + 183 171 191 174 125 115 + 129 143 211 182 153 139 + 133 121 112 121 135 146 + 168 179 155 162 149 138 + 134 117 134 106 85 88 + 101 87 67 57 68 95 + 70 23 43 53 30 41 + 54 67 55 65 57 9 + 100000000 31 71 32 19 28 + 40 55 40 65 60 87 + 74 72 59 82 95 117 + 97 83 97 98 137 96 + 109 128 135 131 117 122 + 112 100 107 109 137 155 + 162 140 131 124 149 208 + 162 172 191 186 204 220 + 218 230 203 175 167 154 + 142 167 147 139 157 176 + 190 195 208 219 227 245 + 245 252 259 242 229 214 + 203 196 258 249 209 209 + 164 177 187 224 246 256 + 236 250 250 203 202 227 + 238 294 277 244 258 231 + 207 222 207 149 146 95 + 75 103 129 186 224 240 + 245 199 185 186 133 79 + 88 184 73 139 130 136 + 156 176 187 204 192 212 + 195 146 136 150 164 232 + 195 174 160 154 142 133 + 142 156 159 181 192 163 + 150 137 151 122 105 128 + 94 87 99 112 108 88 + 78 88 64 39 44 64 + 73 51 62 75 88 76 + 86 78 30 21 100000000 40 + 53 40 49 61 76 61 + 86 55 87 95 93 80 + 103 116 138 118 104 118 + 119 158 117 130 149 156 + 152 138 143 133 121 128 + 130 137 155 162 161 152 + 145 170 218 183 193 201 + 207 225 238 239 251 224 + 196 188 175 163 188 168 + 160 178 197 211 216 229 + 240 248 266 266 273 277 + 260 250 235 224 217 279 + 270 230 230 185 198 208 + 245 267 277 257 271 271 + 224 223 248 259 315 298 + 265 278 251 220 243 228 + 149 167 76 95 114 133 + 199 237 253 266 220 206 + 207 154 100 109 205 94 + 179 170 176 196 216 227 + 244 232 252 235 186 176 + 190 204 272 235 214 200 + 194 182 173 182 196 199 + 221 232 203 190 177 191 + 162 145 168 134 127 139 + 152 148 128 118 128 104 + 79 84 104 113 91 102 + 115 128 116 126 118 70 + 61 40 100000000 22 80 89 + 101 46 30 55 15 47 + 65 70 57 80 93 129 + 158 144 158 159 198 157 + 170 189 196 192 178 120 + 110 98 105 107 97 115 + 122 138 129 122 147 178 + 160 170 161 184 202 198 + 216 228 201 173 165 152 + 140 228 208 200 218 237 + 212 256 269 245 253 271 + 243 250 237 220 275 275 + 264 257 319 310 270 270 + 225 238 248 285 307 317 + 297 311 311 264 263 288 + 299 355 338 305 318 291 + 260 283 268 109 128 116 + 135 154 173 239 277 293 + 227 197 246 184 131 77 + 149 245 134 205 196 202 + 222 242 253 270 258 278 + 261 225 215 229 243 298 + 278 253 239 233 221 212 + 221 235 242 264 275 246 + 233 220 234 205 188 211 + 177 170 182 195 187 171 + 161 171 147 122 127 147 + 156 134 145 158 154 140 + 155 161 113 104 83 43 + 100000000 123 132 125 24 8 + 33 28 56 43 48 35 + 58 71 107 184 170 184 + 198 237 183 196 215 222 + 218 204 98 88 76 83 + 85 106 124 131 116 107 + 100 125 184 138 148 167 + 162 180 196 194 206 179 + 151 143 130 118 213 226 + 226 244 215 190 234 247 + 223 231 249 221 228 235 + 218 253 253 242 235 297 + 288 248 261 251 264 274 + 263 285 295 275 289 298 + 290 289 314 325 333 316 + 317 344 318 303 309 294 + 118 122 159 178 197 216 + 282 320 336 221 175 224 + 162 109 55 175 271 160 + 101 92 98 118 138 149 + 166 154 174 157 121 111 + 125 139 194 178 149 135 + 129 117 108 117 131 142 + 164 175 151 161 148 134 + 148 131 130 120 110 98 + 111 83 77 87 99 133 + 135 90 110 114 97 108 + 121 50 36 51 62 76 + 117 96 56 13 100000000 9 + 21 36 21 46 41 68 + 55 53 40 63 76 100 + 80 66 80 94 133 79 + 92 111 118 114 100 103 + 93 81 88 90 118 136 + 143 121 112 105 130 189 + 143 153 172 167 185 201 + 199 211 184 156 148 135 + 123 150 130 122 140 159 + 173 178 191 202 210 228 + 226 233 240 223 212 197 + 186 179 241 232 192 192 + 147 160 170 207 229 239 + 219 233 233 186 185 210 + 221 277 260 227 241 214 + 203 205 190 130 127 126 + 106 113 125 182 220 236 + 226 180 168 167 114 60 + 71 167 56 92 83 89 + 109 129 140 157 145 165 + 148 112 102 116 130 185 + 169 140 126 120 108 99 + 108 122 133 155 166 142 + 152 139 125 139 122 121 + 111 101 89 102 74 68 + 78 90 124 128 81 101 + 105 88 99 112 41 27 + 42 53 67 110 89 95 + 117 129 100000000 12 27 125 + 61 80 59 46 44 31 + 54 67 91 71 57 71 + 85 124 70 83 102 109 + 105 91 94 84 72 79 + 81 109 127 134 112 103 + 96 121 180 134 144 163 + 158 176 192 190 202 175 + 147 139 126 114 141 121 + 113 131 150 164 169 182 + 193 201 219 217 224 231 + 214 203 188 177 170 232 + 223 183 183 138 151 161 + 198 220 230 210 224 224 + 177 176 201 212 268 251 + 218 232 205 194 196 181 + 121 118 117 97 104 116 + 173 211 227 217 171 159 + 158 105 51 62 158 47 + 80 71 77 97 117 128 + 145 133 153 136 100 90 + 104 118 173 157 128 114 + 108 96 87 96 110 121 + 143 154 130 140 127 113 + 127 110 109 99 89 77 + 90 62 56 66 78 112 + 116 69 89 93 76 87 + 100 29 15 30 41 55 + 98 77 83 105 117 48 + 100000000 15 113 49 68 47 + 34 32 19 42 55 79 + 59 45 59 73 112 58 + 71 90 97 93 79 82 + 72 60 67 69 97 115 + 122 100 91 84 109 168 + 122 132 151 146 164 180 + 178 190 163 135 127 114 + 102 129 109 101 119 138 + 152 157 170 181 189 207 + 205 212 219 202 191 176 + 165 158 220 211 171 171 + 126 139 149 186 208 218 + 198 212 212 165 164 189 + 200 256 239 206 220 193 + 182 184 169 109 106 105 + 85 92 104 161 199 215 + 205 159 147 146 93 39 + 50 146 35 181 172 178 + 198 218 229 246 234 254 + 237 201 191 205 219 274 + 258 229 215 209 197 188 + 197 211 222 244 255 231 + 241 228 214 228 211 210 + 200 190 178 191 163 157 + 167 179 172 147 152 172 + 181 159 170 183 130 116 + 131 142 138 129 108 68 + 90 148 149 101 100000000 98 + 34 53 32 19 24 11 + 34 47 83 160 146 160 + 174 213 159 172 191 198 + 194 180 74 64 52 59 + 61 82 100 107 92 83 + 76 101 160 114 124 143 + 138 156 172 170 182 155 + 127 119 106 94 189 202 + 202 220 191 166 210 223 + 199 207 225 197 204 211 + 194 229 229 218 211 273 + 264 224 237 227 240 250 + 239 261 271 251 265 274 + 266 265 290 301 309 292 + 293 320 294 283 285 270 + 94 98 184 186 193 205 + 262 300 316 197 151 200 + 138 85 31 151 247 136 + 197 188 194 214 234 245 + 262 250 270 253 217 207 + 221 235 290 274 245 231 + 225 213 204 213 227 238 + 260 271 247 249 236 230 + 221 204 226 193 186 194 + 207 179 173 177 187 163 + 138 143 163 172 150 161 + 174 146 132 147 158 129 + 120 99 59 81 139 148 + 117 16 100000000 25 44 48 + 35 40 27 50 63 99 + 176 162 176 190 229 175 + 188 207 214 210 196 90 + 80 68 75 77 98 116 + 123 108 99 92 117 176 + 130 140 159 154 172 188 + 186 198 171 143 135 122 + 110 205 218 218 236 207 + 182 226 239 215 223 241 + 213 220 227 210 245 245 + 234 227 289 280 240 253 + 243 256 266 255 277 287 + 267 281 290 282 281 306 + 317 325 308 309 336 310 + 299 301 286 110 114 175 + 194 209 221 278 316 332 + 213 167 216 154 101 47 + 167 263 152 213 204 210 + 230 250 261 278 266 286 + 269 220 210 224 238 306 + 269 248 234 228 216 207 + 216 230 233 255 266 237 + 224 211 225 196 179 202 + 168 161 173 186 182 162 + 152 162 138 113 118 138 + 147 125 136 149 162 150 + 160 152 104 95 74 34 + 56 114 123 135 80 64 + 100000000 19 51 99 104 91 + 114 127 163 192 178 192 + 193 232 191 204 223 230 + 226 212 154 144 132 139 + 125 101 119 126 144 147 + 156 161 182 174 184 165 + 198 216 202 230 242 215 + 195 187 186 174 249 242 + 234 252 251 226 270 283 + 259 267 285 254 257 241 + 224 282 289 278 271 332 + 323 284 297 259 272 282 + 299 321 331 311 325 334 + 298 297 322 333 368 351 + 339 352 325 294 317 302 + 113 132 150 169 188 207 + 273 311 327 231 211 260 + 198 165 111 183 279 168 + 194 185 191 211 231 242 + 259 247 267 250 201 191 + 205 219 287 250 229 215 + 209 197 188 197 211 214 + 236 247 218 205 192 206 + 177 160 183 149 142 154 + 167 163 143 133 143 119 + 94 99 119 128 106 117 + 130 143 131 141 133 85 + 76 55 15 37 95 104 + 116 61 45 70 100000000 32 + 80 85 72 95 108 144 + 173 159 173 174 213 172 + 185 204 211 207 193 135 + 125 113 120 106 82 100 + 107 125 128 137 142 163 + 155 165 146 179 197 183 + 211 223 196 176 168 167 + 155 230 223 215 233 232 + 207 251 264 240 248 266 + 235 238 222 205 263 270 + 259 252 313 304 265 278 + 240 253 263 280 302 312 + 292 306 315 279 278 303 + 314 349 332 320 333 306 + 275 298 283 94 113 131 + 150 169 188 254 292 308 + 212 192 241 179 146 92 + 164 260 149 217 208 214 + 234 254 265 282 270 290 + 273 233 223 237 251 310 + 282 261 247 241 229 220 + 229 243 246 268 279 250 + 237 224 238 209 192 215 + 181 174 186 199 195 175 + 165 175 151 126 131 151 + 160 138 149 162 166 152 + 167 165 117 108 87 47 + 69 127 136 137 93 77 + 102 32 100000000 112 113 104 + 103 88 119 196 182 196 + 206 245 195 208 227 234 + 230 216 104 100 88 89 + 74 50 68 75 93 96 + 106 110 131 123 133 114 + 147 165 151 179 191 164 + 144 136 136 124 198 211 + 238 256 200 175 219 232 + 208 216 234 203 206 190 + 173 231 238 227 220 281 + 272 233 246 263 276 273 + 248 270 280 260 274 283 + 289 301 326 337 317 300 + 302 329 330 307 321 306 + 62 81 163 182 201 220 + 286 324 340 180 160 209 + 147 115 120 187 283 172 + 228 219 225 245 265 276 + 293 281 301 284 235 225 + 239 253 321 284 263 249 + 243 231 222 231 245 248 + 270 281 252 239 226 240 + 211 194 217 183 176 188 + 201 197 177 167 177 153 + 128 133 153 162 140 151 + 164 177 165 175 167 119 + 110 89 49 71 129 138 + 150 95 79 15 34 13 + 100000000 119 106 116 101 132 + 207 193 207 208 247 206 + 219 238 245 241 227 117 + 113 101 102 87 63 81 + 88 106 109 119 123 144 + 136 146 127 160 178 164 + 192 204 177 157 149 149 + 137 211 224 249 267 213 + 188 232 245 221 229 247 + 216 219 203 186 244 251 + 240 233 294 285 246 259 + 274 287 286 261 283 293 + 273 287 296 302 312 337 + 348 330 313 315 342 340 + 309 332 317 75 94 165 + 184 203 222 288 326 342 + 193 173 222 160 128 126 + 198 294 183 157 148 154 + 174 194 205 222 210 230 + 213 177 167 181 195 250 + 234 205 191 185 173 164 + 173 187 198 220 231 207 + 217 204 190 204 187 186 + 176 166 154 167 139 133 + 143 155 167 142 146 166 + 170 153 164 177 106 92 + 107 118 132 124 103 63 + 85 143 125 77 92 93 + 29 48 27 14 100000000 96 + 10 23 59 136 122 136 + 150 189 135 148 167 174 + 170 156 50 40 28 35 + 37 77 85 92 68 59 + 52 77 136 90 100 119 + 114 132 148 146 158 131 + 103 95 82 70 165 178 + 178 196 167 142 186 199 + 175 183 201 173 180 187 + 170 205 205 194 187 249 + 240 200 213 203 216 226 + 215 237 247 227 241 250 + 242 241 266 277 285 268 + 269 296 270 259 261 246 + 89 74 179 162 169 181 + 238 276 292 173 127 176 + 114 61 7 127 223 112 + 170 161 167 187 207 218 + 235 223 243 226 190 180 + 194 208 263 247 218 204 + 198 186 177 186 200 211 + 233 244 220 230 217 203 + 217 200 199 189 179 167 + 180 152 146 156 168 180 + 155 159 179 183 166 177 + 190 119 105 120 131 145 + 137 116 76 98 156 138 + 90 105 106 42 61 40 + 27 13 100000000 23 36 72 + 149 135 149 163 202 148 + 161 180 187 183 169 63 + 53 41 48 50 90 98 + 105 81 72 65 90 149 + 103 113 132 127 145 161 + 159 171 144 116 108 95 + 83 178 191 191 209 180 + 155 199 212 188 196 214 + 186 193 200 183 218 218 + 207 200 262 253 213 226 + 216 229 239 228 250 260 + 240 254 263 255 254 279 + 290 298 281 282 309 283 + 272 274 259 102 87 192 + 175 182 194 251 289 305 + 186 140 189 127 74 20 + 140 236 125 147 138 144 + 164 184 195 212 200 220 + 203 167 157 171 185 240 + 224 195 181 175 163 154 + 163 177 188 210 221 197 + 207 194 180 194 177 176 + 166 156 144 157 129 123 + 133 145 177 152 136 156 + 160 143 154 167 96 82 + 97 108 122 134 113 73 + 95 153 115 67 82 103 + 39 58 37 24 10 86 + 100000000 33 49 126 112 126 + 140 179 125 138 157 164 + 160 146 40 30 18 25 + 47 87 80 87 63 54 + 42 72 131 85 95 114 + 109 127 143 141 153 126 + 93 85 72 60 160 173 + 168 186 162 137 181 194 + 170 178 196 168 175 182 + 165 200 200 189 182 244 + 235 195 208 193 206 216 + 210 232 242 222 236 245 + 232 231 256 267 280 263 + 264 287 260 249 251 236 + 99 69 172 152 159 171 + 228 266 282 168 122 171 + 109 51 17 117 213 102 + 157 148 154 174 194 205 + 222 210 230 213 177 167 + 181 195 250 234 205 191 + 185 173 164 173 187 198 + 220 231 207 217 204 190 + 204 187 186 176 166 154 + 167 139 133 143 155 189 + 167 146 166 170 153 164 + 177 106 92 107 118 132 + 149 128 88 110 168 125 + 77 92 118 54 73 52 + 39 25 96 15 100000000 59 + 136 122 136 150 189 135 + 148 167 174 170 156 44 + 40 28 29 14 80 62 + 69 45 36 46 54 113 + 67 77 96 91 109 125 + 123 135 108 88 80 76 + 64 142 155 178 196 144 + 119 163 176 152 160 178 + 150 157 164 147 182 182 + 171 164 226 217 177 190 + 203 216 217 192 214 224 + 204 218 227 233 241 266 + 277 262 245 246 273 270 + 259 261 246 92 51 182 + 162 169 181 238 276 292 + 150 104 153 91 55 32 + 127 223 112 98 89 95 + 115 135 146 163 151 171 + 154 118 108 122 136 191 + 175 146 132 126 114 105 + 114 128 139 161 172 148 + 158 145 131 145 128 127 + 117 107 95 108 80 74 + 84 96 130 134 87 107 + 111 94 105 118 47 33 + 48 59 73 116 95 101 + 123 135 66 18 33 131 + 67 86 65 52 50 37 + 60 73 100000000 77 63 77 + 91 130 76 89 108 115 + 111 97 100 90 78 85 + 87 115 133 140 118 109 + 102 127 186 140 150 169 + 164 182 198 196 208 181 + 153 145 132 120 147 127 + 119 137 156 170 175 188 + 199 207 225 223 230 237 + 220 209 194 183 176 238 + 229 189 189 144 157 167 + 204 226 236 216 230 230 + 183 182 207 218 274 257 + 224 238 211 200 202 187 + 127 124 123 103 110 122 + 179 217 233 223 177 165 + 164 111 57 68 164 53 + 47 38 44 64 84 95 + 112 100 120 103 74 64 + 78 92 140 149 120 102 + 82 70 79 88 102 113 + 135 146 122 132 119 105 + 123 111 101 100 90 78 + 91 63 57 67 79 113 + 138 98 104 94 105 116 + 129 30 44 59 70 84 + 127 106 121 143 146 77 + 38 53 151 87 106 85 + 72 70 57 80 93 20 + 100000000 14 28 47 86 25 + 12 31 38 47 20 120 + 110 98 105 107 135 153 + 160 138 129 122 147 178 + 160 142 161 156 174 190 + 178 190 136 129 121 108 + 114 96 76 68 86 105 + 119 124 137 148 156 174 + 184 183 199 212 158 143 + 132 125 187 178 138 138 + 93 106 116 153 175 185 + 165 179 179 132 131 156 + 167 223 206 173 187 160 + 174 151 136 147 144 106 + 86 93 96 153 168 192 + 205 169 114 156 123 77 + 39 113 24 35 26 32 + 52 72 83 100 88 108 + 91 60 50 64 78 128 + 135 106 88 68 56 65 + 74 88 99 121 132 108 + 118 105 91 109 97 87 + 86 76 64 77 49 43 + 53 65 99 124 84 90 + 80 91 102 115 16 30 + 45 56 70 113 92 132 + 145 132 63 72 87 153 + 121 140 119 106 104 91 + 114 127 54 34 100000000 14 + 33 72 13 26 45 52 + 48 34 117 129 132 139 + 141 169 158 165 141 132 + 120 150 166 163 130 149 + 144 162 178 166 178 124 + 117 109 96 102 84 64 + 56 74 93 107 112 125 + 136 144 162 172 171 187 + 200 146 131 120 113 175 + 166 126 126 81 94 104 + 141 163 173 153 167 167 + 120 119 144 155 211 194 + 161 175 148 160 139 124 + 181 147 92 72 79 82 + 139 156 180 193 157 102 + 144 111 111 25 101 10 + 160 151 157 177 197 208 + 225 201 221 216 46 36 + 50 64 202 121 92 74 + 54 42 51 60 74 85 + 107 118 94 104 91 77 + 95 96 73 105 126 117 + 81 76 96 106 118 135 + 160 160 143 133 144 155 + 168 109 123 138 149 163 + 189 168 208 221 208 156 + 168 183 229 217 223 215 + 202 200 187 210 223 159 + 139 125 100000000 19 58 138 + 151 170 177 173 159 242 + 240 228 235 237 265 283 + 290 266 257 245 275 291 + 288 255 274 269 287 303 + 291 303 249 242 234 221 + 227 209 189 181 199 218 + 232 237 250 261 269 287 + 297 296 312 325 271 256 + 245 238 282 273 251 251 + 206 219 229 266 263 253 + 270 284 245 226 208 233 + 233 318 301 231 204 177 + 146 180 194 277 272 145 + 125 98 68 125 163 179 + 318 282 227 269 236 207 + 130 226 115 141 132 138 + 158 178 189 206 182 202 + 197 27 17 31 45 183 + 102 73 55 35 23 32 + 41 55 66 88 99 75 + 85 72 58 76 77 54 + 86 107 98 62 57 77 + 87 99 116 141 141 124 + 114 125 136 149 90 104 + 119 130 144 170 149 189 + 202 189 137 149 164 210 + 198 204 196 183 181 168 + 191 204 140 120 106 55 + 100000000 39 119 132 151 158 + 154 140 223 221 209 216 + 218 246 264 271 247 238 + 226 256 272 269 236 255 + 250 268 284 272 284 230 + 223 215 202 208 190 170 + 162 180 199 213 218 231 + 242 250 268 278 277 293 + 306 252 237 226 219 263 + 254 232 232 187 200 210 + 247 244 234 251 265 226 + 207 189 214 214 299 282 + 212 185 158 127 161 175 + 258 253 126 106 79 49 + 106 144 160 299 263 208 + 250 217 188 111 207 96 + 176 167 173 193 213 224 + 241 217 237 232 62 52 + 66 80 218 137 108 90 + 70 58 67 76 90 101 + 123 134 110 120 107 93 + 111 112 89 121 142 133 + 97 92 112 122 134 151 + 176 176 159 149 160 171 + 184 125 139 154 165 179 + 205 184 224 237 224 172 + 184 199 245 233 239 231 + 218 216 203 226 239 175 + 155 141 16 35 100000000 154 + 167 186 193 189 175 258 + 256 244 251 253 281 299 + 306 282 273 261 291 307 + 304 271 290 285 303 319 + 307 319 265 258 250 237 + 243 225 205 197 215 234 + 248 253 266 277 285 303 + 313 312 328 341 287 272 + 261 254 298 289 267 267 + 222 235 245 282 279 269 + 286 300 261 242 224 249 + 249 334 317 247 220 193 + 162 196 210 293 288 161 + 141 114 84 141 179 195 + 334 298 243 285 252 223 + 146 242 131 22 13 19 + 39 59 70 87 75 95 + 78 73 63 77 91 115 + 131 119 101 81 69 78 + 87 101 112 134 145 121 + 131 118 104 122 110 100 + 99 89 77 90 62 56 + 66 78 112 137 97 103 + 93 104 115 128 29 43 + 58 69 83 126 105 145 + 158 145 76 63 78 166 + 112 131 110 97 95 82 + 105 118 45 25 13 27 + 46 85 100000000 13 32 39 + 35 21 104 116 123 130 + 132 160 145 152 128 119 + 107 137 153 150 117 136 + 131 149 165 153 165 111 + 104 96 83 89 71 51 + 43 61 80 94 99 112 + 123 131 149 159 158 174 + 187 133 118 107 100 162 + 153 113 113 68 81 91 + 128 150 160 140 154 154 + 107 106 131 142 198 181 + 148 162 135 160 126 111 + 172 134 105 85 92 95 + 135 143 167 180 144 89 + 131 98 102 38 88 23 + 35 26 32 52 72 83 + 100 88 108 91 86 76 + 90 104 128 144 132 114 + 94 82 91 100 114 125 + 147 158 134 144 131 117 + 135 123 113 112 102 90 + 103 75 69 79 91 125 + 150 110 116 106 117 128 + 141 42 56 71 82 96 + 139 118 133 155 158 89 + 50 65 163 99 118 97 + 84 82 69 92 105 32 + 12 26 40 59 98 13 + 100000000 19 26 35 8 117 + 122 110 117 119 147 158 + 165 141 132 120 150 166 + 163 130 149 144 162 178 + 166 178 124 117 109 96 + 102 84 64 56 74 93 + 107 112 125 136 144 162 + 172 171 187 200 146 131 + 120 113 175 166 126 126 + 81 94 104 141 163 173 + 153 167 167 120 119 144 + 155 211 194 161 175 148 + 173 139 124 159 147 118 + 98 105 108 148 156 180 + 193 157 102 144 111 89 + 51 101 36 29 38 44 + 48 68 79 96 84 104 + 87 96 95 109 123 124 + 140 151 133 113 101 110 + 119 133 144 166 159 153 + 163 150 136 154 142 132 + 131 121 109 122 94 88 + 98 110 144 169 129 135 + 125 136 147 160 61 75 + 90 101 115 158 137 152 + 174 177 108 69 84 182 + 118 137 116 103 101 88 + 111 124 51 31 45 59 + 78 108 32 19 100000000 7 + 16 11 111 123 129 136 + 138 166 152 159 135 126 + 114 144 160 157 124 143 + 138 156 172 160 172 118 + 111 103 90 96 78 58 + 50 68 87 101 106 119 + 130 138 156 166 165 181 + 194 140 125 114 107 169 + 160 120 120 75 88 98 + 135 157 167 147 161 163 + 114 115 140 151 205 188 + 157 171 144 169 135 120 + 178 141 137 117 124 127 + 144 152 176 187 151 96 + 138 105 108 70 97 55 + 22 31 37 41 61 72 + 89 77 97 80 89 91 + 105 119 117 133 147 129 + 109 97 106 115 129 140 + 162 152 149 159 146 132 + 150 138 128 127 117 105 + 118 90 84 94 106 140 + 165 125 131 121 132 143 + 156 57 71 86 97 111 + 154 133 148 170 173 104 + 65 80 178 114 133 112 + 99 97 84 107 120 47 + 27 41 55 74 101 28 + 15 7 100000000 9 18 104 + 116 125 132 134 162 145 + 152 128 119 107 137 153 + 150 117 136 131 149 165 + 153 165 111 104 96 83 + 89 71 51 43 61 80 + 94 99 112 123 131 149 + 159 158 174 187 133 118 + 107 100 162 153 113 113 + 68 81 91 128 150 160 + 140 154 156 107 108 133 + 144 198 181 150 164 137 + 162 128 113 174 134 133 + 113 120 123 137 145 169 + 180 144 89 131 98 104 + 66 90 51 13 22 28 + 32 52 63 80 68 88 + 71 80 98 112 113 108 + 124 138 123 116 104 113 + 122 136 147 169 143 156 + 166 153 139 157 145 135 + 134 124 112 125 97 91 + 101 113 147 172 132 138 + 128 139 150 163 64 78 + 93 104 118 161 140 157 + 179 180 111 74 89 187 + 123 142 121 108 106 93 + 116 129 56 36 48 62 + 81 92 35 24 16 9 + 100000000 27 95 107 134 141 + 140 154 136 143 119 110 + 98 128 144 141 108 127 + 122 140 156 144 156 102 + 95 87 74 80 62 42 + 34 52 71 85 90 103 + 114 122 140 150 149 165 + 178 124 109 98 91 153 + 144 104 104 59 72 82 + 119 141 151 131 145 147 + 98 99 124 135 189 172 + 141 155 128 153 119 104 + 166 125 140 120 127 130 + 128 136 160 171 135 80 + 122 89 113 73 81 58 + 40 34 40 59 79 90 + 107 95 115 98 94 84 + 98 112 135 151 140 122 + 102 90 99 108 122 133 + 155 166 142 152 139 125 + 143 131 121 120 110 98 + 111 83 77 87 99 133 + 158 118 124 114 125 136 + 149 50 64 79 90 104 + 147 126 141 163 166 97 + 58 73 171 107 126 105 + 92 90 77 100 113 40 + 20 34 48 67 106 21 + 8 11 18 27 100000000 122 + 130 118 125 127 155 163 + 170 146 137 125 155 171 + 168 135 154 149 167 183 + 171 183 129 122 114 101 + 107 89 69 61 79 98 + 112 117 130 141 149 167 + 177 176 192 205 151 136 + 125 118 180 171 131 131 + 86 99 109 146 168 178 + 158 172 174 125 126 151 + 162 216 199 168 182 155 + 180 146 131 167 152 126 + 106 113 116 155 163 187 + 198 162 107 149 116 97 + 59 108 44 129 120 126 + 146 166 177 194 182 202 + 185 149 139 153 167 222 + 206 177 163 157 145 136 + 145 159 170 192 203 179 + 189 176 162 176 159 158 + 148 138 126 139 111 105 + 115 127 161 165 118 138 + 142 125 136 149 78 64 + 79 90 104 147 126 106 + 128 166 97 49 64 136 + 72 91 70 57 43 68 + 33 66 31 108 94 108 + 122 161 107 120 139 146 + 142 128 100000000 12 51 58 + 80 120 113 120 96 87 + 75 105 164 118 128 147 + 142 160 176 174 186 159 + 126 118 105 93 178 158 + 150 168 187 170 206 219 + 203 211 229 201 208 215 + 198 233 225 214 207 269 + 260 220 220 175 188 198 + 235 257 267 247 261 261 + 214 213 238 249 305 288 + 255 269 242 231 233 218 + 132 102 154 134 141 153 + 210 248 264 201 155 196 + 142 84 50 99 195 84 + 117 108 114 134 154 165 + 182 170 190 173 137 127 + 141 155 210 194 165 151 + 145 133 124 133 147 158 + 180 191 167 177 164 150 + 164 147 146 136 126 114 + 127 99 93 103 115 149 + 153 106 126 130 113 124 + 137 66 52 67 78 92 + 135 114 94 116 154 85 + 37 52 124 60 79 58 + 45 31 56 21 54 19 + 96 82 96 110 149 95 + 108 127 134 130 116 61 + 100000000 39 46 68 108 101 + 108 84 75 63 93 152 + 106 116 135 130 148 164 + 162 174 147 114 106 93 + 81 166 146 138 156 175 + 158 194 207 191 199 217 + 189 196 203 186 221 213 + 202 195 257 248 208 208 + 163 176 186 223 245 255 + 235 249 249 202 201 226 + 237 293 276 243 257 230 + 219 221 206 120 90 142 + 122 129 141 198 236 252 + 189 143 184 130 72 38 + 87 183 72 129 120 126 + 146 166 177 194 182 202 + 185 149 139 153 167 222 + 206 177 163 157 145 136 + 145 159 170 192 203 179 + 189 176 162 176 159 158 + 148 138 126 139 111 105 + 115 127 161 165 118 138 + 142 125 136 149 78 64 + 79 90 104 147 126 106 + 128 166 97 49 64 136 + 72 91 70 57 43 68 + 33 66 31 108 94 108 + 122 161 107 120 139 146 + 142 128 22 12 100000000 7 + 66 80 62 69 45 36 + 24 54 113 67 77 96 + 91 109 125 123 135 108 + 75 67 54 42 142 155 + 150 168 144 119 163 176 + 152 160 178 150 157 164 + 147 182 182 171 164 226 + 217 177 190 175 188 198 + 192 214 224 204 218 227 + 214 213 238 249 262 245 + 246 269 242 231 233 218 + 92 51 154 134 141 153 + 210 248 264 150 104 153 + 91 33 50 99 195 84 + 136 127 133 153 173 184 + 201 189 209 192 156 146 + 160 174 229 213 184 170 + 164 152 143 152 166 177 + 199 210 186 196 183 169 + 183 166 165 155 145 133 + 146 118 112 122 134 168 + 172 125 145 149 132 143 + 156 85 71 86 97 111 + 154 133 113 135 173 104 + 56 71 143 79 98 77 + 64 50 75 40 73 38 + 115 101 115 129 168 114 + 127 146 153 149 135 15 + 19 7 100000000 59 73 55 + 62 38 29 17 47 106 + 60 70 89 84 102 118 + 116 128 101 68 60 47 + 35 135 148 157 175 137 + 112 156 169 145 153 171 + 143 150 157 140 175 175 + 164 157 219 210 170 183 + 182 195 205 185 207 217 + 197 211 220 221 220 245 + 256 255 238 239 266 249 + 238 240 225 85 44 161 + 141 148 160 217 255 271 + 143 97 146 84 26 57 + 106 202 91 143 134 140 + 160 180 191 208 196 216 + 199 163 153 167 181 236 + 220 191 177 171 159 150 + 159 173 184 206 217 193 + 203 190 176 190 173 172 + 162 152 140 153 125 119 + 129 141 175 179 132 152 + 156 139 150 163 92 78 + 93 104 118 161 140 102 + 124 180 111 63 78 132 + 68 87 66 53 39 82 + 29 14 45 122 108 122 + 136 175 121 134 153 160 + 156 142 30 26 14 15 + 100000000 66 48 55 31 22 + 32 40 99 53 63 82 + 77 95 111 109 121 94 + 74 66 62 50 128 141 + 164 182 130 105 149 162 + 138 146 164 136 143 150 + 133 168 168 157 150 212 + 203 163 176 189 202 203 + 178 200 210 190 204 213 + 219 227 252 263 248 231 + 232 259 256 245 247 232 + 78 37 168 148 155 167 + 224 262 278 136 90 139 + 77 41 46 113 209 98 + 167 158 164 184 204 215 + 232 220 240 223 187 177 + 191 205 260 244 215 201 + 195 183 174 183 197 208 + 230 241 217 227 214 200 + 214 197 196 186 176 164 + 177 149 143 153 165 199 + 176 156 176 180 163 174 + 187 116 102 117 128 142 + 158 137 97 119 177 135 + 87 102 127 92 82 50 + 77 63 106 53 38 69 + 146 132 146 160 199 145 + 158 177 184 180 166 54 + 50 38 39 24 100000000 18 + 25 43 46 56 60 81 + 73 83 64 97 115 101 + 129 141 114 94 86 86 + 74 148 161 188 206 150 + 125 169 182 158 166 184 + 153 156 140 123 181 188 + 177 170 231 222 183 196 + 213 226 223 198 220 230 + 210 224 233 239 251 276 + 287 267 250 252 279 280 + 269 271 256 12 31 192 + 172 179 191 248 286 302 + 130 110 159 97 65 70 + 137 233 122 185 176 182 + 202 222 233 234 238 258 + 241 205 195 209 223 278 + 262 233 219 213 201 192 + 201 215 226 248 259 235 + 245 232 218 232 215 214 + 204 194 182 195 167 161 + 171 183 217 194 174 194 + 198 181 192 205 134 120 + 135 146 160 176 155 115 + 137 195 153 105 120 145 + 110 100 68 95 81 124 + 71 56 87 164 150 164 + 178 217 163 176 195 202 + 198 184 72 68 56 57 + 42 18 100000000 7 25 60 + 72 42 63 55 65 46 + 79 97 83 111 123 96 + 76 68 102 90 130 143 + 206 224 132 107 151 164 + 140 148 166 135 138 122 + 105 163 170 159 152 213 + 204 165 178 197 210 205 + 180 202 212 192 206 215 + 221 253 278 274 249 232 + 234 261 282 287 273 258 + 30 31 210 190 197 209 + 266 290 314 112 92 141 + 79 81 88 155 225 140 + 182 173 179 199 219 230 + 227 235 255 238 202 192 + 206 220 275 259 230 216 + 210 198 189 198 212 223 + 245 256 232 242 229 215 + 229 212 211 201 191 179 + 192 164 158 168 180 214 + 201 171 191 195 178 189 + 202 131 117 132 143 157 + 183 162 122 144 202 150 + 102 117 152 107 107 75 + 92 78 121 68 53 84 + 161 147 161 175 214 160 + 173 192 199 195 181 69 + 65 53 54 39 25 7 + 100000000 18 53 65 35 56 + 48 58 39 72 90 76 + 104 116 89 69 61 95 + 83 123 136 203 221 125 + 100 144 157 133 141 159 + 128 131 115 98 156 163 + 152 145 206 197 158 171 + 190 203 198 173 195 205 + 185 199 208 214 246 271 + 267 242 225 227 254 275 + 284 266 251 37 24 207 + 187 194 206 263 283 307 + 105 85 134 72 74 85 + 152 218 137 164 155 161 + 181 201 212 209 217 237 + 220 184 174 188 202 257 + 241 212 198 192 180 171 + 180 194 205 227 238 214 + 224 211 197 211 194 193 + 183 173 161 174 146 140 + 150 162 196 200 153 173 + 177 160 171 184 113 99 + 114 125 139 182 161 123 + 145 201 132 84 99 153 + 89 108 85 74 60 103 + 50 35 66 143 129 143 + 157 196 142 155 174 181 + 177 163 51 47 35 36 + 21 35 17 24 100000000 35 + 47 17 76 30 40 59 + 54 72 88 86 98 71 + 51 43 77 65 105 118 + 185 203 107 82 126 139 + 115 123 141 113 120 127 + 110 145 145 134 127 189 + 180 140 153 172 185 180 + 155 177 187 167 181 190 + 196 228 253 250 225 208 + 209 236 257 266 248 233 + 47 6 189 169 176 188 + 245 265 289 113 67 116 + 54 56 67 134 200 119 + 173 164 170 190 210 221 + 210 220 240 229 193 183 + 197 211 260 250 221 207 + 201 189 180 189 203 214 + 236 247 223 233 220 206 + 220 203 202 192 182 170 + 183 155 149 159 171 205 + 209 162 182 186 169 180 + 193 122 108 123 134 148 + 191 170 132 154 210 141 + 93 108 162 98 117 94 + 83 69 112 59 44 75 + 152 138 152 166 205 151 + 164 183 190 186 172 45 + 56 44 45 30 44 26 + 33 9 100000000 12 18 77 + 31 41 60 55 73 89 + 87 99 72 52 44 42 + 30 106 119 190 208 108 + 83 127 140 116 124 142 + 114 121 128 111 146 146 + 135 128 190 181 141 154 + 173 186 181 156 178 188 + 168 182 191 197 229 254 + 251 226 209 210 237 258 + 275 249 234 56 15 198 + 178 185 197 254 266 290 + 114 68 117 55 21 76 + 143 201 128 162 153 159 + 179 199 210 222 215 235 + 218 182 172 186 200 255 + 239 210 196 190 178 169 + 178 192 203 225 236 212 + 222 209 195 209 192 191 + 181 171 159 172 144 138 + 148 160 194 198 151 171 + 175 158 169 182 111 97 + 112 123 137 180 159 139 + 161 199 130 82 97 169 + 105 124 103 90 76 101 + 66 56 64 141 127 141 + 155 194 140 153 172 179 + 175 161 33 45 56 57 + 42 56 38 45 21 12 + 100000000 30 89 43 53 72 + 67 85 101 99 111 84 + 51 43 30 18 118 131 + 183 201 120 95 139 152 + 128 136 154 126 133 140 + 123 158 158 147 140 202 + 193 153 166 185 198 193 + 168 190 200 180 194 203 + 209 241 266 263 238 221 + 222 249 270 264 261 246 + 68 27 187 167 174 186 + 243 278 297 126 80 129 + 67 9 83 132 213 117 + 191 182 188 188 208 219 + 192 202 222 227 211 201 + 215 229 242 258 239 225 + 219 207 198 207 221 232 + 254 265 241 251 238 224 + 238 221 220 210 200 188 + 201 173 167 177 189 223 + 227 180 200 204 187 198 + 211 140 126 141 152 166 + 209 188 150 172 228 159 + 111 126 180 116 135 112 + 101 87 130 77 62 93 + 170 156 170 184 223 169 + 182 201 208 204 190 63 + 74 62 63 48 62 44 + 51 27 18 30 100000000 59 + 13 23 42 37 55 71 + 69 81 54 34 26 60 + 48 88 101 172 190 90 + 65 109 122 98 106 124 + 96 103 110 93 128 128 + 117 110 172 163 123 136 + 155 168 163 138 160 170 + 150 164 173 179 211 236 + 233 208 191 192 219 240 + 265 231 216 74 33 216 + 196 203 215 262 248 272 + 96 50 99 37 39 94 + 161 183 146 193 198 204 + 188 208 219 192 202 222 + 227 227 217 231 245 242 + 258 255 241 235 223 214 + 223 237 248 270 277 257 + 267 254 240 254 237 236 + 226 216 204 217 189 183 + 193 205 239 243 196 216 + 220 203 214 227 156 142 + 157 168 182 225 204 166 + 188 244 175 127 142 196 + 132 151 128 117 103 146 + 93 78 109 186 172 186 + 200 239 185 198 217 215 + 206 206 79 90 78 79 + 64 78 60 67 43 34 + 46 16 100000000 13 23 42 + 37 55 71 69 81 54 + 50 42 76 64 88 101 + 172 190 90 65 109 122 + 98 106 124 96 103 110 + 93 128 128 117 110 172 + 163 123 136 155 168 163 + 138 160 170 150 164 173 + 179 211 236 233 208 191 + 192 219 240 265 231 216 + 90 49 232 212 219 231 + 262 248 272 96 50 99 + 37 55 110 177 183 162 + 180 189 195 175 195 206 + 179 189 209 214 223 247 + 261 234 229 245 259 244 + 255 253 244 253 267 278 + 300 264 287 297 284 270 + 284 267 266 256 246 234 + 247 219 213 223 235 269 + 269 226 246 250 233 244 + 257 186 172 187 198 212 + 251 230 190 212 270 205 + 157 172 220 175 175 143 + 160 146 176 136 121 139 + 216 202 216 230 235 202 + 215 209 202 193 220 108 + 120 121 122 107 93 75 + 68 86 80 92 62 46 + 100000000 10 29 24 42 58 + 56 68 41 64 88 87 + 93 75 88 159 177 77 + 52 96 109 85 93 111 + 83 90 97 80 115 115 + 104 97 159 150 110 123 + 142 155 150 125 147 157 + 137 151 160 166 198 223 + 220 195 178 179 206 227 + 252 218 203 105 92 262 + 242 249 261 249 235 259 + 83 37 86 24 101 153 + 207 170 192 170 179 185 + 165 185 196 169 179 199 + 204 213 237 251 224 219 + 235 249 234 245 243 234 + 243 257 268 290 254 277 + 287 274 260 274 257 256 + 246 236 224 237 209 203 + 213 225 259 259 216 236 + 240 223 234 247 176 162 + 177 188 202 241 220 180 + 202 260 195 147 162 210 + 165 165 133 150 136 166 + 126 111 129 206 192 206 + 220 225 192 205 199 192 + 183 210 98 110 111 112 + 97 83 65 58 76 70 + 82 52 36 49 100000000 19 + 14 32 48 46 58 31 + 54 78 77 83 65 78 + 149 167 67 42 86 99 + 75 83 101 73 80 87 + 70 105 105 94 87 149 + 140 100 113 132 145 140 + 115 137 147 127 141 150 + 156 188 213 210 185 168 + 169 196 217 242 208 193 + 95 82 252 232 239 251 + 239 225 249 73 27 76 + 14 91 143 197 160 182 + 210 212 218 205 225 236 + 209 219 239 244 241 231 + 245 259 259 275 269 255 + 249 237 228 237 251 262 + 284 294 271 281 268 254 + 268 251 250 240 230 218 + 231 203 197 207 219 253 + 240 210 230 234 217 228 + 241 170 156 171 182 196 + 222 201 161 183 241 189 + 141 156 191 146 146 114 + 131 117 160 107 92 123 + 200 186 200 214 253 199 + 212 231 232 223 220 96 + 104 92 93 78 64 46 + 39 57 51 63 33 17 + 30 40 100000000 54 53 37 + 67 79 71 67 59 93 + 81 105 118 189 207 107 + 82 126 139 96 104 122 + 89 92 76 59 117 145 + 134 127 167 158 140 153 + 172 185 180 155 168 178 + 167 181 190 196 228 239 + 228 203 186 200 227 254 + 282 248 233 76 63 246 + 226 233 245 279 265 286 + 66 67 116 54 72 124 + 191 200 176 207 216 222 + 202 222 233 206 216 236 + 241 250 249 263 261 256 + 272 286 271 267 255 246 + 255 269 280 302 287 289 + 299 286 272 286 269 268 + 258 248 236 249 221 215 + 225 237 271 258 228 248 + 252 235 246 259 188 174 + 189 200 214 240 219 179 + 201 259 207 159 174 209 + 164 164 132 149 135 178 + 125 110 141 218 204 218 + 232 262 217 230 236 229 + 220 238 114 122 110 111 + 96 82 64 57 75 69 + 81 51 35 48 58 18 + 100000000 18 34 32 44 68 + 85 77 111 99 102 115 + 186 204 104 79 123 136 + 61 69 87 59 66 73 + 56 91 142 131 124 141 + 132 137 150 169 182 177 + 152 142 152 164 178 187 + 193 225 213 202 177 160 + 174 201 228 259 245 230 + 94 81 264 244 251 263 + 276 262 260 59 63 113 + 72 90 142 209 197 194 + 189 198 204 184 204 215 + 188 198 218 223 232 256 + 270 243 238 254 268 253 + 264 262 253 262 276 287 + 309 269 296 306 293 279 + 293 276 275 265 255 243 + 256 228 222 232 244 278 + 282 235 255 259 242 253 + 266 195 181 196 207 221 + 264 243 214 236 283 214 + 166 181 244 189 199 167 + 174 160 185 150 145 148 + 225 211 225 239 244 211 + 224 218 211 202 229 117 + 129 145 146 131 117 99 + 92 110 104 116 86 70 + 83 86 53 53 100000000 16 + 14 26 50 73 109 96 + 102 84 97 168 186 86 + 61 105 118 43 51 69 + 41 48 55 38 73 124 + 113 106 123 114 119 132 + 151 164 159 134 124 134 + 146 160 169 175 207 195 + 184 159 142 156 183 210 + 241 227 212 129 116 271 + 251 258 270 258 244 242 + 41 45 95 100 111 167 + 216 179 201 205 214 220 + 200 220 231 204 214 234 + 239 248 268 282 259 254 + 270 284 269 280 274 265 + 274 288 299 321 276 305 + 318 305 291 305 288 287 + 277 267 255 268 240 234 + 244 256 290 277 247 267 + 271 254 265 278 207 193 + 208 219 233 259 238 198 + 220 278 226 178 193 228 + 183 183 151 168 154 197 + 144 129 160 237 223 237 + 251 260 227 240 234 227 + 218 245 133 141 129 130 + 115 101 83 76 94 88 + 100 70 54 67 77 37 + 69 16 100000000 30 42 66 + 89 96 112 118 100 113 + 184 202 102 77 121 134 + 59 67 85 52 55 39 + 22 80 140 129 122 130 + 121 135 148 167 180 175 + 150 131 141 158 172 181 + 191 223 202 191 166 149 + 163 190 217 248 243 228 + 113 100 283 263 270 282 + 274 260 249 29 61 111 + 91 109 161 228 195 213 + 175 184 190 170 190 201 + 174 184 204 209 218 242 + 256 229 224 240 254 239 + 250 248 239 248 262 273 + 295 255 282 292 279 265 + 279 262 261 251 241 229 + 242 214 208 218 230 264 + 268 221 241 245 228 239 + 252 181 167 182 193 207 + 250 229 209 231 269 200 + 152 167 239 175 194 171 + 160 146 171 136 149 134 + 211 197 211 225 230 197 + 210 204 197 188 215 103 + 115 149 150 135 121 103 + 96 114 108 106 90 74 + 87 72 57 39 33 49 + 100000000 12 36 59 95 82 + 88 70 83 154 172 72 + 47 91 104 29 37 55 + 27 34 50 34 59 110 + 99 92 109 100 105 118 + 137 150 145 120 110 120 + 132 146 155 161 193 181 + 170 145 128 142 169 196 + 227 213 198 133 120 257 + 237 244 256 244 230 228 + 27 31 81 86 97 153 + 202 165 187 163 172 178 + 158 178 189 162 172 192 + 197 206 230 244 217 212 + 228 242 227 238 236 227 + 236 250 261 283 247 270 + 280 267 253 267 250 249 + 239 229 217 230 202 196 + 206 218 252 256 209 229 + 233 216 227 240 169 155 + 170 181 195 238 217 197 + 219 257 188 140 155 227 + 163 182 159 148 134 159 + 124 137 122 199 185 199 + 213 218 185 198 192 185 + 176 203 91 103 137 138 + 123 109 91 84 102 96 + 94 78 62 75 60 45 + 27 21 37 35 100000000 24 + 47 83 70 76 58 71 + 142 160 60 35 79 92 + 17 25 43 53 60 76 + 59 59 98 87 80 109 + 100 93 106 125 138 133 + 108 110 120 120 134 143 + 149 181 181 170 145 128 + 142 169 196 227 201 186 + 121 108 245 225 232 244 + 232 218 228 62 19 69 + 74 85 141 190 153 175 + 139 148 154 134 154 165 + 138 148 168 173 182 206 + 220 193 188 204 218 203 + 214 212 203 212 226 237 + 259 223 246 256 243 229 + 243 226 225 215 205 193 + 206 178 172 182 194 228 + 232 185 205 209 192 203 + 216 145 131 146 157 171 + 214 193 173 195 233 164 + 116 131 203 139 158 137 + 124 110 135 100 126 98 + 175 161 175 189 194 161 + 174 168 161 152 179 67 + 79 118 125 112 119 101 + 94 91 82 70 88 72 + 85 36 55 50 68 84 + 82 94 100000000 23 59 46 + 52 34 47 118 136 36 + 11 55 68 79 87 105 + 109 114 123 106 89 74 + 63 56 118 109 69 82 + 101 114 109 84 106 116 + 96 110 119 125 157 182 + 179 154 137 138 165 186 + 211 177 162 131 97 221 + 201 208 220 208 194 218 + 109 63 45 50 61 117 + 166 129 151 183 192 198 + 178 198 209 182 192 212 + 217 226 250 264 237 232 + 248 262 247 258 256 247 + 256 270 281 303 267 290 + 300 287 273 287 270 269 + 259 249 237 250 222 216 + 226 238 272 272 229 249 + 253 236 247 260 189 175 + 190 201 215 254 233 193 + 215 273 208 160 175 223 + 178 178 146 163 149 179 + 139 124 142 219 205 219 + 233 238 205 218 212 205 + 196 223 111 123 124 125 + 110 96 78 71 89 83 + 95 65 49 62 13 32 + 27 45 61 59 71 44 + 100000000 91 90 96 78 91 + 162 180 80 55 99 112 + 88 96 114 86 93 100 + 83 118 118 107 100 162 + 153 113 126 145 158 153 + 128 150 160 140 154 163 + 169 201 226 223 198 181 + 182 209 230 255 221 206 + 108 95 265 245 252 264 + 252 238 262 86 40 89 + 27 104 156 210 173 195 + 191 200 206 186 206 217 + 190 200 220 225 234 258 + 272 245 240 256 270 255 + 266 264 255 264 278 289 + 311 275 298 308 295 281 + 295 278 277 267 257 245 + 258 230 224 234 246 280 + 280 237 257 261 244 255 + 268 197 183 198 209 223 + 262 241 201 223 281 216 + 168 183 231 186 186 154 + 171 157 187 147 132 150 + 227 213 227 241 246 213 + 226 220 213 204 231 119 + 131 132 133 118 104 86 + 79 97 91 103 73 57 + 70 21 40 35 53 69 + 67 79 52 8 100000000 98 + 104 86 99 170 188 88 + 63 107 120 96 104 122 + 94 101 108 91 126 126 + 115 108 170 161 121 134 + 153 166 161 136 158 168 + 148 162 171 177 209 234 + 231 206 189 190 217 238 + 263 229 214 116 103 273 + 253 260 272 260 246 270 + 94 48 97 35 112 164 + 218 181 203 204 213 219 + 199 219 230 203 213 233 + 238 247 271 285 258 253 + 269 283 268 279 277 268 + 277 291 302 324 288 311 + 321 308 294 308 291 290 + 280 270 258 271 243 237 + 247 259 293 293 250 270 + 274 257 268 281 210 196 + 211 222 236 275 254 214 + 236 294 229 181 196 244 + 199 199 167 184 170 200 + 160 145 163 240 226 240 + 254 259 226 239 233 226 + 217 244 132 144 145 146 + 131 117 99 92 110 104 + 116 86 70 83 34 53 + 48 66 82 80 92 65 + 21 13 100000000 117 99 112 + 183 201 101 76 120 133 + 109 117 135 107 114 121 + 104 139 139 128 121 183 + 174 134 147 166 179 174 + 149 171 181 161 175 184 + 190 222 247 244 219 202 + 203 230 251 276 242 227 + 129 116 286 266 273 285 + 273 259 283 107 61 110 + 48 125 177 231 194 216 + 144 135 141 161 181 192 + 209 197 217 200 164 154 + 168 182 237 221 192 178 + 172 160 151 160 174 185 + 207 218 194 204 191 177 + 191 174 173 163 153 141 + 154 126 120 130 142 176 + 180 133 153 157 140 151 + 164 93 79 94 105 119 + 162 141 121 143 181 112 + 64 79 151 87 106 85 + 72 58 83 48 74 46 + 123 109 123 137 176 122 + 135 154 161 157 143 15 + 27 66 73 60 74 56 + 63 39 30 18 48 100 + 61 64 83 78 96 112 + 110 122 95 51 43 30 + 100000000 129 142 165 183 131 + 106 150 163 139 147 165 + 137 144 151 134 169 169 + 158 151 213 204 164 177 + 190 203 204 179 201 211 + 191 205 214 220 228 253 + 264 249 232 233 260 257 + 246 248 233 86 45 169 + 149 156 168 225 263 279 + 137 91 140 78 9 65 + 114 210 99 151 153 159 + 146 166 177 150 160 180 + 185 182 172 186 200 200 + 216 210 196 190 178 169 + 178 192 203 225 235 212 + 222 209 195 209 192 191 + 181 171 159 172 144 138 + 148 160 194 198 151 171 + 175 158 169 182 111 97 + 112 123 137 180 159 139 + 161 199 130 82 97 169 + 105 124 103 90 76 101 + 66 92 64 141 127 141 + 155 194 140 153 172 173 + 164 161 33 45 84 91 + 78 92 74 81 57 48 + 36 66 82 79 46 65 + 60 78 94 92 104 77 + 33 25 12 18 100000000 59 + 130 148 48 23 67 80 + 91 99 117 119 126 133 + 116 101 86 75 68 130 + 121 81 94 113 126 121 + 96 118 128 108 122 131 + 137 169 194 191 166 149 + 150 177 198 223 189 174 + 104 63 187 167 174 186 + 220 206 230 119 73 57 + 60 27 83 132 141 117 + 171 173 179 166 186 197 + 170 180 200 205 202 192 + 206 220 220 236 230 216 + 210 198 189 198 212 223 + 245 255 232 242 229 215 + 229 212 211 201 191 179 + 192 164 158 168 180 214 + 218 171 191 195 178 189 + 202 131 117 132 143 157 + 200 179 159 181 219 150 + 102 117 189 125 144 123 + 110 96 121 86 112 84 + 161 147 161 175 214 160 + 173 192 193 184 181 53 + 65 104 111 98 112 94 + 101 77 68 56 86 102 + 99 66 85 80 98 114 + 112 124 97 53 45 32 + 38 20 100000000 150 168 68 + 43 87 100 111 119 137 + 139 146 153 136 121 106 + 95 88 150 141 101 114 + 133 146 141 116 138 148 + 128 142 151 157 189 214 + 211 186 169 170 197 218 + 243 209 194 124 83 207 + 187 194 206 240 226 250 + 139 93 77 80 47 103 + 152 161 137 21 30 36 + 16 36 47 64 52 72 + 55 64 106 120 97 92 + 108 122 107 118 112 121 + 125 139 150 172 127 156 + 169 156 142 160 153 142 + 142 132 120 133 105 99 + 109 121 155 180 140 146 + 136 147 158 171 72 86 + 101 112 126 169 148 167 + 189 188 119 106 121 197 + 133 152 131 118 104 125 + 94 120 88 68 56 70 + 89 76 43 56 50 43 + 34 61 61 73 112 119 + 106 120 102 109 85 76 + 64 94 110 107 74 93 + 88 106 122 110 122 68 + 61 53 40 46 28 8 + 100000000 18 37 51 56 69 + 80 88 106 116 115 131 + 144 90 75 64 57 119 + 110 70 70 25 38 48 + 85 107 117 97 111 120 + 64 83 108 119 155 138 + 125 139 112 137 103 88 + 132 91 148 128 135 138 + 112 120 144 137 101 46 + 88 55 111 81 53 66 + 45 54 60 40 60 71 + 59 69 89 79 88 130 + 144 114 109 125 139 124 + 135 136 145 142 156 167 + 189 144 173 186 173 159 + 177 177 159 166 156 144 + 157 129 123 133 145 179 + 204 164 170 160 171 182 + 195 96 110 125 136 150 + 193 172 191 213 212 143 + 130 145 221 157 176 155 + 142 128 149 118 144 112 + 92 80 94 113 100 67 + 80 74 67 58 85 85 + 97 136 143 130 144 126 + 133 109 100 88 118 122 + 131 86 105 100 118 134 + 92 104 50 73 77 64 + 70 52 32 24 100000000 19 + 61 38 51 62 70 88 + 98 97 113 126 72 57 + 46 39 101 92 52 52 + 7 20 30 67 89 99 + 79 93 102 46 78 103 + 114 137 120 120 134 107 + 132 98 83 156 115 172 + 152 159 162 129 115 139 + 119 113 28 100 79 135 + 105 35 90 103 112 118 + 98 118 129 102 112 132 + 137 146 188 202 157 152 + 168 182 167 178 188 194 + 185 199 210 232 187 216 + 229 216 202 220 225 202 + 224 214 202 215 187 181 + 191 203 237 262 216 228 + 218 223 234 247 154 162 + 177 188 202 245 224 204 + 226 264 195 147 162 234 + 170 189 168 155 141 166 + 131 157 129 150 138 152 + 171 158 125 138 132 125 + 116 143 98 110 149 156 + 143 150 132 125 122 113 + 101 119 103 116 67 86 + 81 99 115 73 85 31 + 54 90 77 83 65 78 + 82 100 100000000 42 19 32 + 43 51 69 79 78 94 + 107 53 38 27 20 82 + 73 33 46 65 78 73 + 48 70 80 60 74 83 + 89 121 146 143 118 101 + 102 129 150 175 141 126 + 162 128 230 210 217 207 + 172 158 182 100 94 9 + 81 92 148 163 93 148 + 128 137 143 123 143 154 + 127 137 157 162 171 195 + 209 182 177 193 207 192 + 203 201 192 201 215 226 + 248 212 235 245 232 218 + 232 215 214 204 194 182 + 195 167 161 171 183 217 + 221 174 194 198 181 192 + 205 134 120 135 146 160 + 203 182 162 184 222 153 + 105 120 192 128 147 126 + 113 99 124 89 115 87 + 164 150 164 178 183 150 + 163 157 150 141 168 56 + 68 107 114 101 115 97 + 104 80 71 59 89 105 + 102 69 88 83 101 117 + 98 110 56 56 48 35 + 41 23 36 107 125 25 + 100000000 44 57 68 76 94 + 104 103 119 132 78 63 + 52 45 107 98 58 71 + 90 103 98 73 95 105 + 85 99 108 114 146 171 + 168 143 126 127 154 175 + 200 166 151 127 86 210 + 190 197 209 197 183 207 + 125 96 34 83 50 106 + 155 118 140 151 160 166 + 146 166 177 150 160 180 + 185 194 218 232 205 200 + 216 230 215 226 224 215 + 224 238 249 271 235 258 + 268 255 241 255 238 237 + 227 217 205 218 190 184 + 194 206 240 244 197 217 + 221 204 215 228 157 143 + 158 169 183 226 205 185 + 207 245 176 128 143 215 + 151 170 149 136 122 147 + 112 138 110 187 173 187 + 201 206 173 186 180 173 + 164 191 79 91 130 137 + 124 131 113 106 103 94 + 82 100 84 97 48 67 + 62 80 96 54 66 12 + 35 71 58 64 46 59 + 130 148 48 23 100000000 13 + 24 32 50 60 67 83 + 88 66 86 75 68 116 + 107 81 94 113 126 121 + 96 117 127 108 122 131 + 137 169 188 177 152 135 + 149 176 198 223 189 174 + 143 109 233 213 220 232 + 220 206 230 81 75 57 + 62 73 129 178 141 163 + 188 197 203 183 203 214 + 187 197 217 222 231 273 + 287 242 237 253 267 252 + 263 273 279 270 284 287 + 309 249 278 291 301 287 + 305 303 287 292 282 270 + 283 255 249 259 271 305 + 309 262 282 286 269 280 + 293 222 208 223 234 248 + 291 270 250 272 310 241 + 193 208 280 216 235 212 + 201 187 212 177 190 175 + 235 223 237 256 243 210 + 223 217 210 201 228 144 + 156 190 191 176 162 144 + 137 155 149 147 131 115 + 128 113 98 80 74 90 + 41 53 77 100 136 123 + 129 111 124 167 185 113 + 88 132 100000000 11 19 37 + 47 54 70 75 53 145 + 134 133 103 94 118 131 + 150 163 158 133 104 114 + 131 145 154 174 200 175 + 164 139 122 136 163 190 + 221 226 211 174 161 298 + 278 285 292 257 237 222 + 68 72 122 127 138 194 + 243 178 228 177 186 192 + 172 192 203 176 186 206 + 211 220 262 276 231 226 + 242 256 241 252 262 268 + 259 273 276 298 238 267 + 280 290 276 294 292 276 + 281 271 259 272 244 238 + 248 260 294 298 251 271 + 275 258 269 282 211 197 + 212 223 237 280 259 239 + 261 299 230 182 197 269 + 205 224 201 190 176 201 + 166 179 164 224 212 226 + 245 232 199 212 206 199 + 190 217 133 145 179 180 + 165 151 133 126 144 138 + 136 120 104 117 102 87 + 69 63 79 30 42 66 + 89 125 112 118 100 113 + 156 174 102 77 121 134 + 100000000 8 26 36 43 59 + 64 42 134 123 122 92 + 83 107 120 139 152 147 + 122 93 103 120 134 143 + 163 189 164 153 128 111 + 125 152 179 210 215 200 + 163 150 287 267 274 281 + 246 226 211 57 61 111 + 116 127 183 232 167 217 + 169 178 184 164 184 195 + 168 178 198 203 212 254 + 268 223 218 234 248 233 + 244 254 260 251 265 268 + 290 230 259 272 282 268 + 286 284 268 273 263 251 + 264 236 230 240 252 286 + 290 243 263 267 250 261 + 274 203 189 204 215 229 + 272 251 231 253 291 222 + 174 189 261 197 216 193 + 182 168 193 158 171 156 + 216 204 218 237 224 191 + 204 198 191 182 209 125 + 137 171 172 157 143 125 + 118 136 130 128 112 96 + 109 94 79 61 55 71 + 22 34 58 81 117 104 + 110 92 105 148 166 94 + 69 113 126 51 100000000 18 + 28 35 51 56 34 126 + 115 114 84 75 99 112 + 131 144 139 114 85 95 + 112 126 135 155 181 156 + 145 120 103 117 144 171 + 202 207 192 155 142 279 + 259 266 273 238 218 203 + 49 53 103 108 119 175 + 224 159 209 151 160 166 + 146 166 177 150 160 180 + 185 194 236 250 205 200 + 216 230 215 226 236 242 + 233 247 250 272 212 241 + 254 264 250 268 273 250 + 272 262 250 263 235 229 + 239 251 285 305 258 276 + 266 265 276 289 202 204 + 219 230 244 287 266 246 + 268 306 237 189 204 276 + 212 231 208 197 183 208 + 173 186 171 198 186 200 + 219 206 173 186 180 173 + 164 191 140 152 186 187 + 172 158 140 133 151 145 + 143 127 111 124 109 94 + 76 70 72 37 49 73 + 96 132 119 125 107 120 + 130 148 109 84 128 141 + 66 74 100000000 10 17 33 + 50 16 108 97 129 66 + 57 81 94 113 126 121 + 96 67 77 94 108 117 + 137 163 138 127 102 85 + 99 126 153 184 189 174 + 170 157 278 258 265 255 + 220 200 185 57 68 118 + 123 134 190 211 141 196 + 167 176 182 162 182 193 + 166 176 196 201 210 252 + 266 221 216 232 246 231 + 242 252 258 249 263 266 + 288 228 257 270 280 266 + 284 289 266 278 268 256 + 269 241 235 245 257 291 + 295 248 268 272 255 266 + 279 208 194 209 220 234 + 277 256 236 258 296 227 + 179 194 266 202 221 198 + 187 173 198 163 176 161 + 214 202 216 235 222 189 + 202 196 189 180 207 130 + 142 176 177 162 148 130 + 123 141 135 133 117 101 + 114 99 84 66 60 62 + 27 39 63 86 122 109 + 115 97 110 146 164 99 + 74 118 131 56 64 82 + 100000000 7 23 40 32 124 + 113 119 82 73 97 110 + 129 142 137 112 83 93 + 110 124 133 153 179 154 + 143 118 101 115 142 169 + 200 205 190 160 147 284 + 264 271 271 236 216 201 + 47 58 108 113 124 180 + 227 157 212 160 169 175 + 155 175 186 159 169 189 + 194 203 245 259 214 209 + 225 239 224 235 245 251 + 242 256 259 281 221 250 + 263 273 259 277 282 259 + 281 271 259 272 244 238 + 248 260 294 302 255 275 + 275 262 273 286 211 201 + 216 227 241 284 263 243 + 265 303 234 186 201 273 + 209 228 205 194 180 205 + 170 183 168 207 195 209 + 228 215 182 195 189 182 + 173 200 137 149 183 184 + 169 155 137 130 148 142 + 140 124 108 121 106 91 + 73 67 55 34 46 70 + 93 129 116 122 104 117 + 139 157 106 81 125 138 + 63 71 89 7 100000000 16 + 33 25 117 106 126 75 + 66 90 103 122 135 130 + 105 76 86 103 117 126 + 146 172 147 136 111 94 + 108 135 162 193 198 183 + 167 154 287 267 274 264 + 229 209 194 40 65 115 + 120 131 187 220 150 205 + 176 185 191 171 191 202 + 175 185 205 210 219 261 + 275 230 225 241 255 240 + 251 261 267 258 272 275 + 297 237 266 279 289 275 + 293 298 275 297 287 275 + 288 260 254 264 276 310 + 316 271 291 291 278 289 + 302 227 217 232 243 257 + 298 277 237 259 317 250 + 202 217 267 222 222 190 + 207 193 221 183 168 184 + 223 211 225 244 231 198 + 211 205 198 189 216 153 + 165 168 169 154 140 122 + 115 133 127 139 109 93 + 106 116 76 89 55 39 + 50 62 86 109 135 132 + 138 120 133 155 173 122 + 97 141 154 79 87 105 + 23 16 100000000 17 41 133 + 122 142 91 82 106 119 + 138 151 146 121 92 102 + 119 133 142 162 188 163 + 152 127 110 124 151 178 + 209 214 199 152 139 303 + 283 290 280 245 225 210 + 24 81 131 130 147 200 + 236 166 221 193 202 208 + 188 208 219 192 202 222 + 227 236 276 290 247 242 + 258 272 257 268 278 273 + 275 289 292 314 254 283 + 296 306 292 310 296 292 + 285 275 263 276 248 242 + 252 264 298 299 255 275 + 279 262 273 286 215 201 + 216 227 241 281 260 220 + 242 300 234 186 201 250 + 205 205 173 190 176 205 + 166 151 168 240 228 242 + 259 248 215 228 222 215 + 206 233 137 149 151 152 + 137 123 105 98 116 110 + 122 92 76 89 99 59 + 73 38 22 34 46 70 + 93 118 116 122 104 117 + 172 190 106 81 125 138 + 63 71 89 30 33 17 + 100000000 58 144 133 126 108 + 99 123 136 155 168 163 + 138 109 119 136 150 159 + 179 205 180 169 144 127 + 141 168 195 226 231 216 + 135 122 291 271 278 290 + 262 242 227 7 65 115 + 113 131 183 236 183 221 + 135 144 150 130 150 161 + 134 144 164 169 178 220 + 234 189 184 200 214 199 + 210 220 226 217 231 234 + 256 196 225 238 248 234 + 252 257 234 256 246 234 + 247 219 213 223 235 269 + 294 254 260 250 261 272 + 285 186 200 215 226 240 + 283 262 268 290 302 233 + 211 226 298 234 253 230 + 219 205 230 195 208 193 + 182 170 184 203 190 157 + 170 164 157 148 175 162 + 174 208 209 194 180 162 + 155 173 167 165 149 133 + 146 131 116 98 92 80 + 59 71 95 118 154 141 + 147 129 122 114 132 93 + 106 112 125 88 96 114 + 32 25 41 58 100000000 92 + 81 113 50 41 65 78 + 97 110 105 80 51 61 + 78 92 101 121 147 122 + 111 86 69 83 110 137 + 168 173 158 192 179 262 + 242 249 239 204 184 169 + 65 90 102 145 156 212 + 195 125 180 129 138 144 + 124 144 155 128 138 158 + 163 172 214 228 183 178 + 194 208 193 204 214 220 + 211 225 228 250 190 219 + 232 242 228 246 251 228 + 250 240 228 241 213 207 + 217 229 263 288 248 254 + 244 255 266 279 180 194 + 209 220 234 277 256 248 + 270 296 227 191 206 278 + 214 233 210 199 185 210 + 175 188 173 176 164 178 + 197 184 151 164 158 151 + 142 169 142 154 188 189 + 174 160 142 135 153 147 + 145 129 113 126 111 96 + 78 72 88 39 51 75 + 98 134 121 127 109 116 + 108 126 87 86 106 119 + 68 17 35 45 40 56 + 73 15 100000000 75 107 44 + 35 59 72 91 104 99 + 74 45 55 72 86 95 + 115 141 116 105 80 63 + 77 104 131 162 167 152 + 172 159 256 236 243 233 + 198 178 163 66 70 96 + 125 136 192 189 119 174 + 140 149 155 135 155 166 + 139 149 169 174 183 225 + 239 194 189 205 219 204 + 215 225 231 222 236 239 + 261 201 230 243 253 239 + 257 262 239 261 251 239 + 252 224 218 228 240 274 + 299 259 265 255 266 277 + 290 191 205 220 231 245 + 288 267 259 281 307 238 + 202 217 289 225 244 221 + 210 196 221 186 199 184 + 187 175 189 208 195 162 + 175 169 162 153 180 153 + 165 199 200 185 171 153 + 146 164 158 156 140 124 + 137 122 107 89 83 99 + 50 62 86 109 145 132 + 138 120 127 119 137 98 + 97 117 130 79 28 46 + 56 51 67 84 26 11 + 100000000 118 55 46 70 83 + 102 115 110 85 56 66 + 83 97 106 126 152 127 + 116 91 74 88 115 142 + 173 178 163 183 170 267 + 247 254 244 209 189 174 + 77 81 107 136 147 203 + 200 130 185 147 156 162 + 142 162 173 146 156 176 + 181 190 232 246 201 196 + 212 226 211 222 232 238 + 229 243 246 268 208 237 + 250 260 246 264 269 246 + 268 258 246 259 231 225 + 235 247 281 306 266 272 + 262 273 284 297 198 212 + 227 238 252 295 274 264 + 286 314 245 207 222 294 + 230 249 226 215 201 226 + 191 204 189 194 182 196 + 215 202 169 182 176 169 + 160 187 158 170 204 205 + 190 176 158 151 169 163 + 161 145 129 142 127 112 + 94 88 104 55 67 91 + 114 150 137 143 125 134 + 126 144 105 102 124 14 + 25 33 51 61 58 74 + 89 33 18 7 100000000 62 + 53 77 90 109 122 117 + 92 63 73 90 104 113 + 133 159 134 123 98 81 + 95 122 149 180 185 170 + 188 175 274 254 261 251 + 216 196 181 82 86 114 + 141 152 208 207 137 192 + 85 94 100 80 100 111 + 84 94 114 119 128 170 + 184 139 134 150 164 149 + 160 170 176 167 181 192 + 214 169 198 211 198 184 + 202 207 184 206 196 184 + 197 169 163 173 185 219 + 244 204 210 200 211 222 + 235 136 150 165 176 190 + 233 212 231 253 252 183 + 170 185 261 197 216 195 + 182 168 189 158 184 152 + 132 120 134 153 140 107 + 120 114 107 98 125 125 + 137 176 183 170 184 166 + 168 149 140 128 158 146 + 159 110 129 120 114 130 + 81 93 74 97 117 104 + 110 92 72 64 82 43 + 85 62 75 86 59 77 + 87 82 98 115 57 42 + 31 63 100000000 62 15 28 + 47 60 55 30 52 62 + 42 56 65 71 103 128 + 132 107 90 84 111 132 + 157 123 108 196 155 212 + 192 199 189 154 140 164 + 108 112 52 124 119 175 + 145 75 130 94 103 109 + 89 109 120 93 103 123 + 128 137 179 193 148 143 + 159 173 158 169 179 185 + 176 190 193 215 155 184 + 197 207 193 211 216 193 + 215 205 193 206 178 172 + 182 194 228 253 213 219 + 209 220 231 244 145 159 + 174 185 199 242 221 240 + 262 261 192 179 194 270 + 206 225 204 191 177 198 + 167 193 161 141 129 143 + 162 149 116 129 123 116 + 107 134 134 146 185 192 + 179 193 175 177 158 149 + 137 167 155 168 119 138 + 129 123 121 90 102 83 + 106 126 113 119 101 81 + 73 91 52 94 71 84 + 95 68 86 73 66 82 + 99 41 51 40 72 9 + 100000000 24 37 56 69 64 + 39 10 20 37 51 60 + 80 106 81 70 45 28 + 42 69 96 127 132 117 + 205 164 221 201 208 198 + 163 143 128 106 121 61 + 133 128 184 154 84 139 + 70 79 85 65 85 96 + 69 79 99 104 113 155 + 169 124 119 135 149 134 + 145 155 161 152 166 177 + 199 154 183 196 183 169 + 187 192 169 191 181 169 + 182 154 148 158 170 204 + 229 189 195 185 196 207 + 220 121 135 150 161 175 + 218 197 216 238 237 168 + 155 170 246 182 201 180 + 167 153 174 143 169 137 + 117 105 119 138 125 92 + 105 99 92 83 110 110 + 122 161 168 155 169 151 + 153 134 125 113 143 131 + 144 95 114 109 127 143 + 101 113 59 82 102 89 + 95 77 57 49 67 28 + 70 47 60 71 79 97 + 107 106 122 135 81 66 + 55 48 56 47 100000000 13 + 32 45 40 15 37 47 + 27 41 50 56 88 113 + 117 92 75 69 96 117 + 142 108 93 181 140 197 + 177 184 174 139 125 149 + 128 122 37 109 104 160 + 130 60 115 57 66 72 + 52 72 83 71 81 101 + 91 100 142 156 126 121 + 137 151 136 147 148 157 + 154 168 179 201 156 185 + 198 185 171 189 189 171 + 178 168 156 169 141 135 + 145 157 191 216 176 182 + 172 183 194 207 108 122 + 137 148 162 205 184 203 + 225 224 155 142 157 233 + 169 188 167 154 140 161 + 130 156 124 104 92 106 + 125 112 79 92 86 79 + 70 97 97 109 148 155 + 142 156 138 140 121 112 + 100 130 118 131 82 101 + 96 114 130 88 100 46 + 69 89 76 82 64 44 + 36 54 15 57 34 47 + 58 66 84 94 93 109 + 122 68 53 42 35 97 + 88 48 100000000 19 32 42 + 63 85 95 75 89 98 + 58 90 115 126 133 116 + 117 144 119 144 110 95 + 168 127 184 164 171 174 + 141 127 151 115 109 24 + 96 91 147 117 47 102 + 38 47 53 33 53 64 + 52 62 82 72 81 123 + 137 107 102 118 132 117 + 128 129 138 135 149 160 + 182 137 166 179 166 152 + 170 170 152 159 149 137 + 150 122 116 126 138 172 + 197 157 163 153 164 175 + 188 89 103 118 129 143 + 186 165 184 206 205 136 + 123 138 214 150 169 148 + 135 121 142 111 137 105 + 85 73 87 106 93 60 + 73 67 60 51 78 78 + 90 129 136 123 137 119 + 126 102 93 81 111 127 + 124 91 110 105 123 139 + 127 139 85 78 70 57 + 63 45 25 17 35 54 + 68 73 86 97 105 123 + 133 132 148 161 107 92 + 81 74 136 127 87 45 + 100000000 13 23 102 124 134 + 114 128 119 39 71 96 + 107 172 155 113 127 100 + 125 91 76 149 108 165 + 145 152 155 122 108 132 + 154 118 63 105 72 128 + 98 28 83 44 53 59 + 39 59 70 39 49 69 + 78 87 129 143 94 89 + 105 119 104 115 125 131 + 122 136 147 169 124 153 + 166 153 139 157 162 139 + 165 155 143 156 128 122 + 132 144 178 203 163 169 + 159 170 181 194 95 109 + 124 135 149 192 171 190 + 212 211 142 129 144 220 + 156 175 154 141 127 148 + 117 143 111 91 79 93 + 112 99 66 79 73 66 + 57 84 84 96 135 142 + 129 143 125 132 108 99 + 87 117 133 130 97 116 + 111 129 145 120 132 78 + 84 76 63 69 51 31 + 23 41 47 74 66 79 + 90 98 116 126 125 141 + 154 100 85 74 67 129 + 120 80 32 48 100000000 10 + 95 117 122 107 121 106 + 26 58 83 94 165 148 + 100 114 87 112 78 63 + 155 114 171 151 158 144 + 109 95 119 147 124 56 + 111 78 134 104 15 89 + 79 88 94 74 94 105 + 29 39 59 75 84 148 + 162 84 79 95 109 94 + 105 115 121 112 126 137 + 159 114 143 156 143 129 + 147 152 129 163 184 178 + 147 146 157 167 179 193 + 218 198 204 194 205 216 + 229 130 144 159 170 184 + 227 206 225 247 246 177 + 164 179 255 191 210 189 + 176 162 183 152 178 146 + 126 114 112 131 96 101 + 114 108 101 92 119 119 + 131 170 177 164 178 160 + 162 143 134 122 152 140 + 153 104 123 118 136 152 + 110 122 68 91 111 98 + 104 86 66 58 76 37 + 79 56 69 80 88 106 + 116 115 131 144 90 75 + 64 57 119 110 70 22 + 41 54 100000000 85 107 112 + 97 111 96 16 48 73 + 84 155 138 90 104 77 + 102 68 53 190 149 205 + 186 164 134 99 85 109 + 137 131 46 118 113 169 + 139 69 124 104 113 119 + 99 119 130 54 64 84 + 100 109 173 187 109 104 + 120 134 119 130 140 146 + 137 151 162 184 139 168 + 181 168 154 172 177 154 + 188 209 203 172 171 182 + 192 204 218 243 223 229 + 219 230 241 254 155 169 + 184 195 209 252 231 250 + 272 271 202 189 204 280 + 216 235 214 201 187 208 + 177 203 171 151 139 137 + 156 121 126 139 133 126 + 117 144 144 156 195 202 + 189 203 185 187 168 159 + 147 177 165 178 129 148 + 143 155 153 122 134 93 + 116 136 123 129 111 91 + 83 101 62 104 81 94 + 105 100 118 105 98 114 + 131 73 83 72 82 41 + 32 56 47 66 79 25 + 100000000 22 32 12 26 35 + 41 73 98 102 77 60 + 54 81 102 127 93 78 + 215 174 230 211 189 159 + 124 110 134 138 153 71 + 143 138 194 164 94 149 + 104 113 119 99 119 130 + 93 103 123 138 147 189 + 203 148 143 159 173 158 + 169 179 185 176 190 183 + 205 145 174 187 200 193 + 211 216 193 225 215 203 + 211 188 182 192 204 238 + 263 223 229 219 230 241 + 254 155 169 184 195 209 + 252 231 250 272 271 202 + 189 204 280 216 235 214 + 201 187 208 177 203 171 + 151 139 153 172 159 126 + 139 133 126 117 144 144 + 156 195 202 189 203 185 + 187 168 159 147 177 165 + 178 129 148 139 133 131 + 100 112 93 116 136 123 + 129 111 91 83 101 62 + 104 81 94 105 78 96 + 83 76 92 109 51 61 + 50 82 19 10 34 47 + 66 79 64 39 100000000 10 + 27 41 50 75 112 91 + 80 55 38 32 59 86 + 117 132 117 215 174 231 + 211 218 198 163 133 118 + 116 131 71 143 138 194 + 164 94 149 114 123 129 + 109 129 140 83 93 113 + 129 138 199 213 138 133 + 149 163 148 159 169 175 + 166 180 173 195 135 164 + 177 190 183 201 206 183 + 217 225 213 201 198 192 + 202 214 247 272 233 239 + 229 240 251 264 165 179 + 194 205 219 262 241 260 + 282 281 212 199 214 290 + 226 245 224 211 197 218 + 187 213 181 161 149 163 + 182 150 136 149 143 136 + 127 154 154 166 205 212 + 199 213 195 197 178 169 + 157 187 175 188 139 158 + 149 143 141 110 122 103 + 126 146 133 139 121 101 + 93 111 72 114 91 104 + 115 88 106 93 86 102 + 119 61 71 60 92 29 + 20 44 57 76 89 54 + 29 10 100000000 17 31 40 + 65 102 89 78 65 48 + 22 49 76 107 122 107 + 225 184 241 221 218 188 + 153 123 108 126 141 81 + 153 148 204 174 104 159 + 116 125 131 111 131 142 + 66 76 96 112 121 185 + 199 121 116 132 146 131 + 142 152 158 149 163 174 + 196 151 180 193 180 166 + 184 189 166 200 221 215 + 184 183 194 204 216 230 + 255 235 241 231 242 253 + 266 167 181 196 207 221 + 264 243 262 284 283 214 + 201 216 292 228 247 226 + 213 199 220 189 215 183 + 163 151 149 168 133 138 + 151 145 138 129 156 156 + 168 207 214 201 215 197 + 199 180 171 159 189 177 + 190 141 160 155 167 165 + 134 146 105 128 148 135 + 141 123 103 95 113 74 + 116 93 106 117 112 130 + 117 110 126 143 85 95 + 84 94 53 44 68 59 + 78 91 37 12 34 44 + 100000000 14 23 48 85 110 + 114 89 72 66 93 114 + 139 105 90 227 186 242 + 223 201 171 136 122 146 + 150 165 83 155 150 206 + 176 106 161 129 129 123 + 124 128 139 56 66 86 + 102 111 175 189 111 106 + 122 136 121 132 142 148 + 139 153 164 186 141 170 + 183 170 156 174 179 156 + 190 211 214 174 173 193 + 203 215 220 245 239 240 + 230 241 252 265 171 185 + 200 211 225 268 247 275 + 297 287 218 205 220 305 + 241 260 239 226 212 224 + 202 228 187 167 155 139 + 158 123 142 155 158 151 + 142 163 169 181 220 227 + 214 228 210 212 193 184 + 172 202 190 203 154 173 + 168 186 202 160 172 118 + 141 161 148 154 136 116 + 108 126 87 129 106 119 + 130 138 156 166 165 181 + 194 140 125 114 107 168 + 159 120 72 91 104 50 + 135 149 139 147 100000000 9 + 34 75 100 111 204 187 + 117 131 104 129 95 80 + 240 199 232 221 191 161 + 126 112 136 187 181 96 + 168 163 219 180 119 165 + 120 120 114 115 119 130 + 47 57 77 93 102 166 + 180 102 97 113 127 112 + 123 133 139 130 144 155 + 177 132 161 174 161 147 + 165 170 147 181 202 205 + 165 164 184 194 206 211 + 236 230 231 221 232 243 + 256 162 176 191 202 216 + 259 238 266 288 278 209 + 196 211 296 232 251 230 + 217 203 215 193 219 178 + 158 146 130 149 114 133 + 146 149 142 133 154 160 + 172 211 218 205 219 201 + 203 184 175 163 193 181 + 194 145 164 159 177 193 + 151 163 109 132 152 139 + 145 127 107 99 117 78 + 120 97 110 121 129 147 + 157 156 172 185 131 116 + 105 98 159 150 111 63 + 82 95 41 126 140 130 + 138 152 100000000 25 66 91 + 102 195 178 108 122 95 + 120 86 71 231 190 223 + 212 182 152 117 103 127 + 178 172 87 159 154 210 + 171 110 156 95 95 89 + 90 94 105 22 32 52 + 68 77 141 155 77 72 + 88 102 87 98 108 114 + 105 119 130 152 107 136 + 149 136 122 140 145 122 + 156 177 180 140 139 159 + 169 181 186 211 205 206 + 196 207 218 231 137 151 + 166 177 191 234 213 241 + 263 253 184 171 186 271 + 207 226 205 192 178 190 + 168 194 153 133 121 105 + 124 89 108 121 124 117 + 108 129 135 147 186 193 + 180 194 176 178 159 150 + 138 168 156 169 120 139 + 134 152 168 126 138 84 + 107 127 114 120 102 82 + 74 92 53 95 72 85 + 96 104 122 132 131 147 + 160 106 91 80 73 134 + 125 86 38 57 70 16 + 101 115 105 113 127 89 + 100000000 41 66 77 170 153 + 83 97 70 95 61 46 + 206 165 198 187 157 127 + 92 78 102 153 147 62 + 134 129 185 146 85 131 + 113 113 107 108 112 123 + 40 50 70 86 95 146 + 160 56 51 67 81 66 + 77 87 93 84 98 109 + 131 86 115 128 115 101 + 119 124 101 135 156 159 + 119 118 138 148 160 165 + 190 202 185 175 186 197 + 210 151 165 180 191 205 + 231 210 250 263 250 198 + 189 204 271 225 244 223 + 210 196 208 186 212 171 + 151 139 123 129 107 126 + 139 142 135 126 147 153 + 165 204 211 198 212 194 + 196 177 168 156 186 174 + 187 138 157 152 170 186 + 144 156 102 125 145 132 + 138 120 100 92 110 71 + 113 90 103 114 122 140 + 150 149 165 178 124 109 + 98 91 93 84 104 56 + 75 88 34 93 74 64 + 81 95 48 18 100000000 25 + 36 129 112 42 56 29 + 60 29 14 224 183 177 + 166 136 106 71 46 61 + 171 165 80 152 147 203 + 164 103 149 138 138 132 + 133 137 148 65 75 95 + 111 120 171 185 81 76 + 92 106 91 102 112 118 + 109 123 134 156 111 140 + 153 140 126 144 149 126 + 160 181 184 144 143 163 + 173 185 190 215 227 210 + 200 211 222 235 176 190 + 205 216 230 256 235 275 + 288 275 223 214 229 296 + 250 269 248 235 221 233 + 211 237 196 176 164 148 + 154 132 151 164 167 160 + 151 172 178 190 229 236 + 223 237 219 221 202 193 + 181 211 199 212 163 182 + 177 182 180 149 161 127 + 150 170 157 163 145 125 + 117 135 96 138 115 128 + 139 127 145 132 125 141 + 158 100 110 99 116 68 + 59 83 81 100 113 59 + 68 49 39 56 70 23 + 43 25 100000000 11 104 87 + 17 44 54 85 54 39 + 249 208 202 191 161 131 + 96 71 86 165 180 105 + 177 172 228 189 128 174 + 132 132 126 127 131 142 + 59 69 89 105 114 178 + 192 92 87 103 117 102 + 113 123 129 120 134 145 + 167 122 151 164 151 137 + 155 160 137 171 192 195 + 155 154 174 184 196 201 + 226 238 221 211 222 233 + 246 174 188 203 214 228 + 267 246 278 299 286 221 + 208 223 307 244 263 242 + 229 215 227 205 231 190 + 170 158 142 161 126 145 + 158 161 154 145 166 172 + 184 223 230 217 231 213 + 215 196 187 175 205 193 + 206 157 176 171 189 191 + 160 172 121 144 164 151 + 157 139 119 111 129 90 + 132 109 122 133 138 156 + 143 136 152 169 111 121 + 110 110 79 70 94 75 + 94 107 53 79 60 50 + 67 81 12 37 36 11 + 100000000 115 98 28 55 65 + 96 65 50 243 202 213 + 202 172 142 107 82 97 + 176 184 99 171 166 222 + 183 122 168 157 157 151 + 152 156 167 84 94 114 + 130 139 203 217 117 112 + 128 142 127 138 148 154 + 145 159 170 192 147 176 + 189 176 162 180 185 162 + 196 217 220 180 179 199 + 209 221 226 251 263 246 + 236 247 258 271 199 213 + 228 239 253 292 271 303 + 324 311 246 233 248 332 + 269 288 267 254 240 252 + 230 256 215 195 183 167 + 186 151 170 183 186 179 + 170 191 197 209 248 255 + 242 256 238 240 221 212 + 200 230 218 231 182 201 + 196 214 216 185 197 146 + 169 189 176 182 164 144 + 136 154 115 157 134 147 + 158 163 181 168 161 177 + 194 136 146 135 135 104 + 95 119 100 119 132 78 + 104 85 75 92 106 37 + 62 61 36 25 100000000 123 + 53 80 90 121 90 75 + 268 227 238 227 197 167 + 132 107 122 201 209 124 + 196 191 247 208 147 193 + 174 174 168 169 173 184 + 101 111 131 147 156 220 + 234 134 129 145 159 144 + 155 165 171 162 176 187 + 209 164 193 206 193 179 + 197 202 179 213 234 237 + 197 196 216 226 238 243 + 268 280 263 253 264 275 + 288 216 230 245 256 270 + 309 288 320 341 328 263 + 250 265 349 286 305 284 + 271 257 269 247 273 232 + 212 200 184 203 168 187 + 200 203 196 187 208 214 + 226 265 272 259 273 255 + 257 238 229 217 247 235 + 248 199 218 213 231 233 + 202 214 163 186 206 193 + 199 181 161 153 171 132 + 174 151 164 175 180 198 + 185 178 194 211 153 163 + 152 152 121 112 136 117 + 136 149 95 121 102 92 + 109 123 54 79 78 53 + 42 17 100000000 70 97 107 + 138 107 92 285 244 255 + 244 214 184 149 124 139 + 218 226 141 213 208 264 + 225 164 210 136 145 151 + 131 151 162 105 115 135 + 151 160 221 235 143 138 + 154 168 153 164 174 180 + 171 162 151 173 113 142 + 155 168 182 183 200 188 + 211 232 235 206 205 214 + 224 236 241 266 255 261 + 251 262 273 286 187 201 + 216 227 241 284 263 282 + 304 303 234 221 236 312 + 248 267 246 233 219 240 + 209 235 203 183 171 185 + 204 172 158 171 165 158 + 149 176 176 188 227 234 + 221 235 217 219 200 191 + 179 209 197 210 161 180 + 171 165 163 132 144 125 + 148 168 155 161 143 123 + 115 133 94 136 113 126 + 137 110 128 115 108 124 + 141 83 93 82 114 51 + 42 66 79 98 111 76 + 51 32 22 39 53 62 + 87 92 67 56 87 70 + 100000000 27 54 85 116 101 + 247 206 253 242 223 193 + 158 101 86 148 163 103 + 175 170 226 196 126 181 + 161 161 155 156 160 171 + 88 98 118 134 143 206 + 220 116 111 127 141 126 + 137 147 153 144 135 124 + 146 86 115 128 141 155 + 156 173 161 184 205 217 + 179 178 198 208 220 214 + 239 262 245 235 246 257 + 270 203 217 232 243 257 + 291 270 307 323 310 250 + 237 252 331 273 292 271 + 258 244 256 234 260 219 + 199 187 171 189 155 174 + 187 190 183 174 195 201 + 213 252 259 246 260 242 + 244 225 216 204 234 222 + 235 186 205 198 192 190 + 159 171 150 173 193 180 + 186 168 148 140 158 119 + 161 138 151 162 137 155 + 142 135 151 168 110 120 + 109 139 78 69 93 104 + 123 136 82 78 59 49 + 66 80 41 66 65 40 + 29 114 97 27 100000000 27 + 58 89 74 272 231 226 + 215 196 166 131 74 59 + 175 190 128 200 195 251 + 212 151 197 155 146 140 + 160 145 156 101 83 103 + 119 128 179 193 89 84 + 100 114 99 110 120 126 + 117 108 97 119 59 88 + 101 114 128 129 146 134 + 157 178 190 152 151 171 + 181 193 187 212 235 218 + 208 219 230 243 184 198 + 213 224 238 264 243 283 + 296 283 231 222 237 304 + 271 290 269 256 254 241 + 247 273 204 184 172 156 + 162 140 159 172 184 177 + 168 180 214 226 265 272 + 259 273 255 257 238 229 + 217 247 235 248 199 218 + 213 219 217 186 198 163 + 186 206 193 199 181 161 + 153 171 132 174 151 164 + 175 164 182 169 162 178 + 195 137 147 136 152 105 + 96 120 117 136 149 95 + 105 86 76 93 107 68 + 79 61 67 56 141 124 + 54 27 100000000 31 62 47 + 285 244 199 188 169 139 + 104 47 32 202 217 141 + 213 208 261 197 164 182 + 127 118 112 132 117 128 + 102 55 75 91 100 151 + 165 61 56 72 86 71 + 82 92 98 89 77 66 + 88 28 57 70 83 97 + 98 115 106 126 147 159 + 124 123 143 153 164 156 + 181 206 189 179 190 201 + 214 156 170 185 196 210 + 235 214 254 267 254 203 + 194 209 275 243 262 241 + 228 226 213 236 249 176 + 156 144 128 134 112 131 + 144 156 149 140 152 209 + 221 254 261 254 268 250 + 257 233 224 212 242 236 + 249 200 219 214 232 248 + 206 218 164 187 201 188 + 194 176 156 148 166 133 + 175 152 165 176 184 202 + 200 193 209 226 168 171 + 160 153 136 127 151 118 + 137 145 96 136 117 107 + 124 138 99 80 62 87 + 87 172 155 85 58 31 + 100000000 34 48 280 239 168 + 157 141 111 76 17 33 + 233 227 142 214 203 233 + 169 146 154 93 84 78 + 98 83 94 69 21 41 + 57 66 117 131 27 22 + 38 52 37 48 58 64 + 55 69 80 102 57 86 + 99 86 72 90 95 72 + 106 127 130 90 89 109 + 119 131 136 161 173 156 + 146 157 168 181 122 136 + 151 162 176 202 181 221 + 234 221 169 160 175 242 + 209 228 207 194 192 179 + 202 215 142 122 110 94 + 100 78 97 110 122 115 + 106 118 175 187 220 227 + 220 234 216 223 199 190 + 178 208 203 216 167 186 + 181 199 215 173 185 131 + 154 167 154 160 142 122 + 114 132 100 142 119 132 + 143 151 169 179 178 194 + 207 153 138 127 120 122 + 113 133 85 104 111 63 + 122 103 93 110 124 77 + 47 29 54 65 158 141 + 71 85 58 34 100000000 15 + 246 205 148 137 107 77 + 42 17 67 200 194 109 + 181 169 199 135 112 120 + 108 99 93 113 98 109 + 54 36 56 72 81 132 + 146 42 37 53 67 52 + 63 73 79 70 84 95 + 117 72 101 114 101 87 + 105 110 87 121 142 145 + 105 104 124 134 146 151 + 176 188 171 161 172 183 + 196 137 151 166 177 191 + 217 196 236 249 236 184 + 175 190 257 224 243 222 + 209 207 194 200 226 157 + 137 125 109 115 93 112 + 125 137 130 121 133 167 + 179 218 225 212 226 208 + 210 191 182 170 200 188 + 201 152 171 166 184 200 + 158 170 116 139 159 146 + 152 134 114 106 124 85 + 127 104 117 128 136 154 + 164 163 179 192 138 123 + 112 105 107 98 118 70 + 89 102 48 107 88 78 + 95 109 62 32 14 39 + 50 143 126 56 70 43 + 49 15 100000000 238 197 163 + 152 122 92 57 32 75 + 185 179 94 166 161 214 + 150 117 135 155 146 152 + 172 192 203 220 208 228 + 211 175 165 179 193 248 + 232 203 189 183 171 162 + 171 185 196 218 229 205 + 215 202 188 202 185 184 + 174 164 152 165 137 131 + 141 153 187 191 144 164 + 168 151 162 175 104 90 + 105 116 130 173 152 114 + 136 192 123 75 90 144 + 80 99 78 65 51 94 + 41 26 57 134 120 134 + 148 187 133 146 165 172 + 168 154 42 38 26 27 + 12 48 30 37 43 34 + 44 52 93 65 75 76 + 89 107 113 121 133 106 + 86 78 74 62 140 153 + 176 194 142 117 161 174 + 150 158 176 148 155 152 + 135 180 180 169 162 224 + 215 175 188 201 214 215 + 190 212 222 202 216 225 + 231 239 264 275 260 243 + 244 271 268 257 259 244 + 100000000 19 180 160 167 179 + 236 274 290 142 102 151 + 89 53 58 125 221 110 + 196 187 193 213 233 244 + 245 249 269 252 216 206 + 220 234 289 273 244 230 + 224 212 203 212 226 237 + 259 270 246 256 243 229 + 243 226 225 215 205 193 + 206 178 172 182 194 228 + 205 185 205 209 192 203 + 216 145 131 146 157 171 + 187 166 126 148 206 164 + 116 131 156 121 111 79 + 106 92 135 82 67 98 + 175 161 175 189 228 174 + 187 206 213 209 195 83 + 79 67 68 53 29 11 + 18 36 71 83 53 74 + 66 76 57 90 108 94 + 122 134 107 87 79 113 + 101 141 154 217 235 143 + 118 162 175 151 159 177 + 146 149 133 116 174 181 + 170 163 224 215 176 189 + 208 221 216 191 213 223 + 203 217 226 232 264 289 + 285 260 243 245 272 293 + 298 284 269 41 100000000 221 + 201 208 220 277 301 325 + 123 103 152 90 92 99 + 166 236 151 141 132 138 + 158 178 189 206 194 214 + 197 107 97 111 125 224 + 143 125 111 115 103 94 + 93 107 107 129 140 111 + 98 85 99 70 53 76 + 42 30 42 55 69 49 + 39 27 12 37 69 52 + 42 53 64 77 90 104 + 88 80 94 97 76 116 + 129 116 106 118 133 137 + 162 131 163 152 150 137 + 160 173 140 120 106 120 + 80 119 119 132 151 158 + 154 140 200 190 178 185 + 187 213 231 238 218 209 + 202 227 272 240 236 255 + 250 268 284 272 284 230 + 223 215 202 208 190 170 + 162 180 199 213 218 231 + 242 250 268 278 277 293 + 306 252 237 226 219 281 + 272 232 232 187 200 210 + 247 269 275 259 273 267 + 226 225 250 255 317 300 + 253 226 199 168 202 216 + 225 224 100000000 20 57 81 + 147 185 201 299 263 208 + 250 211 157 111 207 96 + 121 112 118 138 158 169 + 186 174 194 177 87 77 + 91 105 213 132 114 100 + 95 83 74 82 96 96 + 118 129 100 87 74 88 + 59 42 65 31 10 22 + 35 49 29 19 7 32 + 57 49 32 22 33 44 + 57 70 84 68 60 74 + 78 57 97 110 97 86 + 98 113 118 143 112 144 + 132 130 117 140 153 120 + 100 86 100 60 99 99 + 112 131 138 134 120 180 + 170 158 165 167 194 212 + 219 198 189 182 207 252 + 220 216 235 230 248 264 + 252 264 210 203 195 182 + 188 170 150 142 160 179 + 193 198 211 222 230 248 + 258 257 273 286 232 217 + 206 199 261 252 212 212 + 167 180 190 227 249 259 + 239 253 253 206 205 230 + 241 297 280 242 215 188 + 157 191 205 206 204 20 + 100000000 37 70 136 174 190 + 279 243 188 230 191 137 + 91 187 76 159 150 156 + 176 196 207 224 188 208 + 215 120 110 124 128 189 + 108 90 76 87 97 67 + 58 72 72 94 105 76 + 63 50 64 35 18 41 + 7 28 40 53 82 67 + 57 45 37 62 87 70 + 60 71 82 95 108 122 + 106 98 112 116 95 135 + 148 135 124 136 151 156 + 181 150 182 170 168 155 + 178 191 158 138 124 138 + 93 132 137 150 169 176 + 172 158 218 208 196 203 + 205 232 250 257 236 227 + 220 245 290 258 254 273 + 268 286 302 290 302 248 + 241 233 220 226 208 188 + 180 198 217 231 236 249 + 260 268 286 296 295 311 + 324 270 255 244 237 269 + 260 250 250 205 218 228 + 265 250 240 257 271 232 + 213 195 220 220 305 288 + 218 191 164 133 167 181 + 244 242 49 38 100000000 46 + 112 150 166 317 281 226 + 268 229 175 129 225 114 + 126 117 123 143 163 174 + 191 163 183 182 80 70 + 84 98 164 83 54 40 + 51 61 31 22 36 47 + 69 80 56 66 53 39 + 45 28 5 37 58 70 + 13 42 62 72 75 67 + 92 117 100 90 101 112 + 125 75 89 104 115 129 + 146 125 165 178 165 122 + 134 149 186 183 180 181 + 168 166 153 176 189 125 + 105 91 105 53 92 104 + 117 136 143 139 125 208 + 206 194 201 203 231 249 + 256 232 223 211 241 257 + 254 221 240 235 253 269 + 257 269 215 208 200 187 + 193 175 155 147 165 184 + 198 203 216 227 235 253 + 263 262 278 291 237 222 + 211 204 244 235 217 217 + 172 185 195 232 225 215 + 232 246 207 188 170 195 + 195 280 263 193 166 139 + 108 142 156 243 238 79 + 68 30 100000000 87 125 141 + 284 248 193 235 202 173 + 96 192 81 160 151 157 + 177 197 208 225 183 203 + 216 114 104 118 16 184 + 103 10 24 35 45 51 + 42 56 67 89 100 76 + 86 73 59 77 82 59 + 93 114 117 77 76 96 + 106 118 123 148 160 143 + 133 144 155 168 109 123 + 138 149 163 189 168 208 + 221 208 156 168 183 229 + 217 223 215 202 200 187 + 210 223 159 139 125 139 + 87 126 138 151 170 177 + 173 159 242 240 228 235 + 237 265 283 290 266 257 + 245 275 291 288 255 274 + 269 287 303 291 303 249 + 242 234 221 227 209 189 + 181 199 218 232 237 250 + 261 269 287 297 296 312 + 325 271 256 245 238 264 + 255 251 246 206 219 224 + 264 245 235 252 266 227 + 208 190 215 215 300 283 + 213 186 159 128 162 176 + 277 272 135 124 94 64 + 100000000 145 161 318 282 227 + 269 236 207 130 226 115 + 110 101 95 115 100 111 + 86 38 58 74 83 134 + 148 44 39 55 69 54 + 65 75 81 72 86 83 + 105 45 74 87 100 89 + 107 112 89 123 144 147 + 107 106 126 136 148 153 + 178 190 173 163 174 185 + 198 139 153 168 179 193 + 219 198 238 251 238 186 + 177 192 259 226 245 224 + 211 209 196 219 232 159 + 139 127 111 117 95 114 + 127 139 132 123 135 192 + 204 237 244 237 251 233 + 240 216 207 195 225 220 + 233 184 203 198 216 232 + 190 202 148 171 184 171 + 177 159 139 131 149 117 + 159 136 149 160 168 186 + 196 195 211 224 170 155 + 144 137 139 130 150 102 + 121 128 80 139 120 110 + 127 141 94 64 46 71 + 82 175 158 88 75 48 + 17 17 32 263 222 165 + 154 124 94 59 100000000 50 + 217 211 126 198 186 216 + 152 129 137 123 114 108 + 128 113 124 69 51 71 + 87 96 147 161 57 52 + 68 82 67 78 88 94 + 85 99 98 120 60 89 + 102 115 102 120 125 102 + 136 157 160 120 119 139 + 149 161 166 191 203 186 + 176 187 198 211 152 166 + 181 192 206 232 211 251 + 264 251 199 190 205 272 + 239 258 237 224 222 209 + 215 241 172 152 140 124 + 130 108 127 140 152 145 + 136 148 182 194 233 240 + 227 241 223 225 206 197 + 185 215 203 216 167 186 + 181 199 215 173 185 131 + 154 174 161 167 149 129 + 121 139 100 142 119 132 + 143 151 169 179 178 194 + 207 153 138 127 120 122 + 113 133 85 104 117 63 + 122 103 93 110 124 77 + 47 29 54 65 158 141 + 71 85 58 32 30 15 + 253 212 178 167 137 107 + 72 15 100000000 200 194 109 + 181 176 229 165 132 150 + 190 199 205 185 205 216 + 189 199 219 224 233 269 + 283 244 239 255 269 254 + 265 275 266 272 286 289 + 311 251 280 293 303 289 + 306 289 288 278 268 256 + 269 241 235 245 257 291 + 295 248 268 272 255 266 + 279 208 194 209 220 234 + 277 256 227 249 296 227 + 179 194 257 202 212 180 + 187 173 198 163 158 161 + 237 224 238 252 245 212 + 225 219 212 203 230 130 + 142 158 159 144 130 112 + 105 123 117 129 99 83 + 96 99 66 66 45 29 + 27 39 63 86 122 109 + 115 97 110 169 187 99 + 74 118 131 56 64 82 + 23 30 24 7 55 137 + 126 119 105 96 120 133 + 152 165 160 135 106 116 + 133 147 156 176 202 177 + 166 141 124 138 165 192 + 223 228 213 142 129 284 + 264 271 283 259 239 224 + 100000000 58 108 113 124 180 + 229 180 214 215 224 230 + 210 230 241 214 224 244 + 249 258 257 271 269 264 + 280 294 279 275 263 254 + 263 277 288 310 295 297 + 307 294 280 294 277 276 + 266 256 244 257 229 223 + 233 245 279 266 236 256 + 260 243 254 267 196 182 + 197 208 222 248 227 187 + 209 267 215 167 182 217 + 172 172 140 157 143 186 + 133 118 149 226 212 226 + 240 270 225 238 244 237 + 228 246 122 130 118 119 + 104 90 72 65 83 77 + 89 59 43 56 66 26 + 8 26 42 40 52 76 + 93 85 119 107 110 123 + 194 212 112 87 131 144 + 69 77 95 67 74 81 + 64 99 150 139 132 149 + 140 145 158 177 190 185 + 160 150 160 172 186 195 + 201 233 221 210 185 168 + 182 209 236 267 253 238 + 102 89 272 252 259 271 + 284 270 268 67 100000000 121 + 80 98 150 217 205 202 + 94 103 109 89 109 120 + 93 103 123 128 137 179 + 193 148 143 159 173 158 + 169 179 185 176 190 201 + 223 178 207 220 207 193 + 211 216 193 215 205 193 + 206 178 172 182 194 228 + 253 213 219 209 220 231 + 244 145 159 174 185 199 + 242 221 240 262 261 192 + 179 194 270 206 225 204 + 191 177 198 167 193 161 + 141 129 143 162 149 116 + 129 123 116 107 134 134 + 146 185 192 179 187 169 + 162 158 149 137 156 140 + 153 119 123 105 99 115 + 66 78 83 106 126 113 + 119 101 81 73 91 52 + 94 71 25 36 44 62 + 72 69 85 100 44 29 + 18 11 73 64 24 37 + 56 69 64 39 61 71 + 51 65 74 80 112 137 + 134 109 92 93 120 141 + 166 132 117 199 164 221 + 201 208 198 163 149 173 + 93 97 100000000 133 128 184 + 154 84 139 156 165 171 + 151 171 182 155 165 185 + 190 199 223 237 210 205 + 221 235 220 231 229 220 + 229 243 254 276 240 263 + 273 260 246 260 243 242 + 232 222 210 223 195 189 + 199 211 245 249 202 222 + 226 209 220 233 162 148 + 163 174 188 231 210 190 + 212 250 181 133 148 220 + 156 175 153 141 127 152 + 117 131 115 192 178 192 + 206 211 178 191 185 178 + 169 196 84 96 131 132 + 117 103 85 78 96 90 + 87 72 56 69 53 39 + 21 39 55 53 65 17 + 40 76 63 69 51 64 + 135 153 53 28 72 85 + 82 90 108 80 87 94 + 77 106 91 80 73 135 + 126 86 99 118 131 126 + 101 123 133 113 127 136 + 142 174 199 196 171 154 + 155 182 203 228 194 179 + 115 102 238 218 225 237 + 225 211 235 80 13 62 + 100000000 78 134 183 146 168 + 153 144 150 170 190 201 + 218 206 226 209 173 163 + 177 191 246 230 201 187 + 181 169 160 169 183 194 + 216 227 203 213 200 186 + 200 183 182 172 162 150 + 163 135 129 139 151 185 + 189 142 162 166 149 160 + 173 102 88 103 114 128 + 171 150 130 152 190 121 + 73 88 160 96 115 94 + 81 67 92 57 65 55 + 132 118 132 146 185 131 + 144 163 170 166 152 24 + 36 65 66 51 65 47 + 54 30 21 9 39 91 + 52 55 74 69 87 103 + 101 113 86 42 34 21 + 9 120 133 174 192 122 + 97 141 154 130 138 156 + 128 135 142 125 160 160 + 149 142 204 195 155 168 + 187 200 195 170 192 202 + 182 196 205 211 237 262 + 265 240 223 224 251 266 + 255 257 242 77 36 178 + 158 165 177 234 272 288 + 128 82 131 69 100000000 74 + 123 215 108 173 164 170 + 190 210 221 238 226 246 + 229 193 183 197 211 266 + 250 221 207 201 189 180 + 189 203 214 236 247 223 + 233 220 206 220 203 202 + 192 182 170 183 155 149 + 159 171 205 183 162 182 + 186 169 180 193 122 108 + 123 134 148 165 144 104 + 126 184 141 93 108 134 + 70 89 68 55 41 112 + 31 16 75 152 138 152 + 166 205 151 164 183 190 + 186 172 60 56 44 45 + 30 96 78 85 61 52 + 62 70 129 83 93 112 + 107 125 141 139 151 124 + 104 96 92 80 158 171 + 194 212 160 135 179 192 + 168 176 194 166 173 180 + 163 198 198 187 180 242 + 233 193 206 219 232 233 + 208 230 240 220 234 243 + 249 257 282 293 278 261 + 262 289 286 275 277 262 + 108 67 198 178 185 197 + 254 292 308 166 120 169 + 107 71 100000000 143 239 128 + 56 47 53 73 93 104 + 121 109 129 112 83 73 + 87 101 149 158 129 111 + 91 79 88 97 111 122 + 144 155 131 141 128 114 + 132 120 110 109 99 87 + 100 72 66 76 88 122 + 147 107 113 103 114 125 + 138 39 53 68 79 93 + 136 115 130 152 155 86 + 47 62 160 96 115 94 + 81 79 66 89 102 29 + 9 23 37 56 95 34 + 21 40 47 56 29 129 + 119 107 114 116 144 162 + 169 147 138 131 156 187 + 169 151 170 165 183 199 + 187 199 145 138 130 117 + 123 105 85 77 95 114 + 128 133 146 157 165 183 + 193 192 208 221 167 152 + 141 134 196 187 147 147 + 102 115 125 162 184 194 + 174 188 188 141 140 165 + 176 232 215 182 196 169 + 183 160 145 156 153 115 + 95 102 105 162 177 201 + 214 178 123 165 132 86 + 100000000 122 33 29 38 44 + 24 44 55 72 60 80 + 63 72 114 128 105 100 + 116 130 115 126 120 129 + 133 147 158 180 135 164 + 177 164 150 168 161 150 + 150 140 128 141 113 107 + 117 129 163 188 148 154 + 144 155 166 179 80 94 + 109 120 134 177 156 175 + 197 196 127 114 129 205 + 141 160 139 126 112 133 + 102 128 96 76 64 78 + 97 84 51 64 58 51 + 42 69 69 81 120 127 + 114 128 110 117 93 84 + 72 102 118 115 82 101 + 96 114 130 118 130 76 + 69 61 48 54 36 16 + 8 26 45 59 64 77 + 88 96 114 124 123 139 + 152 98 83 72 65 127 + 118 78 78 33 46 56 + 93 115 125 105 119 128 + 72 91 116 127 163 146 + 133 147 120 145 111 96 + 140 99 156 136 143 146 + 120 128 152 145 109 54 + 96 63 119 89 100000000 74 + 45 36 42 62 82 93 + 110 98 118 101 70 60 + 74 88 138 134 105 91 + 78 66 64 73 87 98 + 120 131 107 117 104 90 + 104 87 86 76 66 54 + 67 39 33 43 55 89 + 114 74 80 70 81 92 + 105 6 20 35 46 60 + 103 82 122 135 122 53 + 62 77 143 111 130 109 + 96 94 81 104 117 44 + 24 10 24 43 82 23 + 36 55 62 58 44 127 + 134 122 129 131 159 168 + 175 151 142 130 160 176 + 173 140 159 154 172 188 + 176 188 134 127 119 106 + 112 94 74 66 84 103 + 117 122 135 146 154 172 + 182 181 197 210 156 141 + 130 123 185 176 136 136 + 91 104 114 151 173 183 + 163 177 177 130 129 154 + 165 221 204 171 185 158 + 159 149 134 171 157 82 + 62 69 81 138 166 190 + 203 167 112 154 121 101 + 15 111 100000000 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv70.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv70.atsp new file mode 100644 index 0000000..a966e49 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ftv70.atsp @@ -0,0 +1,849 @@ +NAME: ftv70 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 71 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 100000000 26 46 74 82 65 + 90 104 102 100 147 134 + 90 75 69 106 117 42 + 71 96 158 89 76 125 + 38 40 58 59 13 38 + 31 22 103 143 106 94 + 137 104 123 140 98 70 + 58 38 30 48 67 118 + 120 105 149 140 100 55 + 115 141 94 93 122 113 + 162 154 76 118 36 21 + 62 165 92 94 66 66 + 100000000 20 48 56 39 126 + 81 76 109 156 140 156 + 141 135 172 183 108 137 + 162 224 155 142 190 104 + 76 124 95 79 104 97 + 88 130 176 133 121 164 + 131 150 167 125 97 85 + 65 57 75 94 145 147 + 132 160 151 80 82 142 + 162 74 67 96 87 189 + 128 103 145 102 66 128 + 176 119 121 40 46 53 + 100000000 28 36 19 106 61 + 56 89 136 120 136 121 + 115 152 163 88 117 142 + 204 135 122 170 84 56 + 104 75 59 84 77 68 + 110 156 113 101 144 111 + 130 147 105 77 65 45 + 37 55 74 125 127 112 + 140 131 60 62 122 142 + 54 47 76 67 169 108 + 83 125 82 46 108 156 + 99 101 20 73 87 72 + 100000000 30 46 133 55 50 + 83 130 114 158 117 137 + 174 185 115 144 169 231 + 162 149 198 111 83 131 + 102 86 111 104 95 176 + 216 179 167 210 176 195 + 182 140 143 131 111 103 + 121 109 160 162 147 131 + 122 94 113 131 133 56 + 38 67 39 235 99 118 + 190 109 94 135 147 162 + 167 70 43 57 42 70 + 100000000 16 103 25 20 53 + 100 84 128 87 107 144 + 155 85 114 139 201 132 + 119 168 81 53 101 72 + 56 81 74 65 146 186 + 149 137 180 147 166 183 + 141 113 101 81 73 91 + 110 161 163 148 164 155 + 102 98 158 166 89 71 + 100 42 205 109 119 161 + 79 64 105 180 135 137 + 62 27 41 26 54 62 + 100000000 87 87 82 97 144 + 131 117 102 96 133 144 + 69 98 123 185 116 103 + 152 65 37 85 56 40 + 65 58 49 130 170 133 + 121 164 131 150 167 125 + 97 85 65 57 75 94 + 145 147 132 166 157 86 + 82 142 168 80 73 102 + 93 189 134 103 145 63 + 48 89 182 119 121 46 + 129 155 175 203 199 194 + 100000000 14 180 38 85 72 + 95 54 74 111 122 87 + 116 141 186 134 146 195 + 117 117 137 65 116 148 + 155 151 218 213 235 223 + 266 233 252 269 227 199 + 187 167 159 177 196 247 + 249 234 260 251 229 184 + 244 262 204 186 155 158 + 255 157 205 247 93 150 + 80 276 221 223 195 137 + 163 183 211 189 202 104 + 100000000 170 28 75 62 103 + 62 82 119 130 95 124 + 149 194 142 154 203 125 + 125 145 73 124 156 163 + 159 226 221 243 231 274 + 241 260 277 235 207 195 + 175 167 185 204 255 257 + 242 250 241 232 192 250 + 252 194 176 145 148 263 + 147 213 255 101 158 88 + 266 229 231 203 106 120 + 105 91 63 79 109 5 + 100000000 33 80 64 108 67 + 87 124 135 100 129 154 + 199 147 159 208 130 116 + 150 78 119 144 137 128 + 209 226 212 200 238 189 + 208 195 153 176 164 144 + 136 154 122 173 175 160 + 144 135 107 126 144 146 + 69 51 80 22 268 89 + 131 203 106 127 93 160 + 175 200 83 109 135 155 + 183 161 174 76 81 142 + 100000000 47 34 75 34 54 + 91 102 67 96 121 166 + 114 126 175 97 97 117 + 45 96 128 135 131 198 + 193 215 203 246 213 232 + 249 207 179 167 147 139 + 157 176 227 229 214 222 + 213 204 164 222 224 166 + 148 117 120 235 119 185 + 227 73 130 60 238 201 + 203 175 157 171 156 141 + 114 130 136 34 95 60 + 100000000 40 135 94 114 151 + 162 127 156 181 226 174 + 186 235 157 157 177 105 + 156 188 188 179 258 253 + 263 251 288 239 258 245 + 203 227 215 195 187 205 + 172 223 207 210 175 166 + 157 176 175 177 119 101 + 70 73 295 72 181 253 + 133 178 120 191 225 251 + 133 143 169 174 159 132 + 148 110 65 113 34 31 + 100000000 102 68 88 122 133 + 101 130 155 197 148 160 + 209 131 131 151 79 130 + 162 169 165 232 227 249 + 237 280 247 266 263 221 + 213 201 181 173 191 190 + 241 225 228 193 184 175 + 194 193 195 137 119 88 + 91 269 90 199 261 107 + 164 94 209 235 237 151 + 117 143 163 191 199 182 + 84 98 204 73 109 91 + 100000000 42 51 44 55 75 + 90 96 119 108 120 165 + 105 105 125 53 104 136 + 143 139 192 187 211 204 + 242 221 240 257 215 187 + 175 155 147 165 184 235 + 237 222 266 257 217 172 + 232 258 211 210 179 182 + 228 181 193 235 81 138 + 68 282 209 211 183 75 + 101 121 149 157 140 42 + 56 176 34 81 68 41 + 100000000 20 57 68 33 62 + 87 132 80 92 141 63 + 63 83 11 62 94 101 + 97 164 159 181 169 212 + 179 198 215 173 145 133 + 113 105 123 142 193 195 + 180 224 215 175 130 190 + 216 169 168 151 154 201 + 153 151 193 39 96 26 + 240 167 169 141 95 121 + 141 169 177 160 62 76 + 196 54 101 88 21 20 + 100000000 37 48 53 82 89 + 112 100 112 158 83 83 + 103 31 82 114 121 117 + 184 179 201 189 232 199 + 218 235 193 165 153 133 + 125 143 162 213 215 200 + 244 235 195 150 210 236 + 189 188 171 174 221 173 + 171 213 59 116 46 260 + 187 189 161 90 116 136 + 164 172 155 99 113 192 + 91 138 122 44 57 37 + 100000000 11 48 46 52 75 + 64 76 121 78 78 98 + 68 77 109 116 112 148 + 143 167 160 198 194 213 + 230 188 160 148 128 120 + 138 157 208 210 195 239 + 230 190 145 205 231 184 + 183 208 203 184 210 166 + 208 54 111 68 255 182 + 178 156 79 105 125 153 + 161 144 99 113 181 91 + 138 125 58 57 37 54 + 100000000 37 35 41 103 53 + 65 114 67 67 87 68 + 66 98 105 101 137 132 + 156 149 187 183 202 219 + 177 149 137 117 109 127 + 146 197 199 184 228 219 + 179 134 194 220 173 172 + 201 192 174 210 155 197 + 43 100 57 244 171 167 + 145 42 68 88 116 124 + 107 75 89 144 67 114 + 101 48 33 27 64 75 + 100000000 29 54 116 47 59 + 108 30 30 50 44 29 + 61 68 64 131 126 148 + 136 179 146 165 182 140 + 112 100 80 72 90 109 + 160 162 147 191 182 142 + 97 157 183 136 135 164 + 155 168 186 118 160 6 + 63 20 207 134 136 108 + 101 127 147 175 183 166 + 134 148 203 126 173 160 + 104 92 83 69 46 59 + 100000000 25 87 18 30 79 + 89 89 109 103 88 120 + 127 123 102 97 121 114 + 152 162 181 208 193 144 + 159 139 131 149 168 219 + 221 206 250 241 201 156 + 216 242 195 194 223 214 + 139 245 177 176 65 122 + 79 266 193 132 167 100 + 126 146 174 182 165 120 + 134 202 112 159 146 79 + 78 58 44 21 58 56 + 100000000 62 71 83 108 88 + 88 108 89 87 119 126 + 122 155 150 174 167 205 + 204 223 240 198 170 158 + 138 130 148 167 218 220 + 205 249 240 200 155 215 + 241 194 193 222 213 171 + 231 176 218 64 121 78 + 265 192 185 166 92 118 + 138 166 174 157 125 139 + 194 117 164 151 98 83 + 77 114 97 50 51 76 + 100000000 9 21 46 80 80 + 100 94 79 111 118 114 + 93 88 112 105 143 153 + 172 199 184 135 150 130 + 122 140 159 210 212 197 + 241 232 192 147 207 233 + 186 185 214 205 130 236 + 168 167 56 113 70 257 + 184 123 158 83 109 129 + 157 165 148 116 130 185 + 108 155 142 89 74 68 + 105 88 41 42 67 129 + 100000000 12 61 71 71 91 + 85 70 102 109 105 84 + 79 103 96 134 144 163 + 190 175 126 141 121 113 + 131 150 201 203 188 232 + 223 183 138 198 224 177 + 176 205 196 121 227 159 + 158 47 104 61 248 175 + 114 149 71 97 117 145 + 153 136 104 118 173 96 + 143 130 77 62 56 93 + 76 29 30 55 117 48 + 100000000 49 59 59 79 73 + 58 90 97 93 72 67 + 91 84 122 132 151 178 + 163 114 129 109 101 119 + 138 189 191 176 220 211 + 171 126 186 212 165 164 + 193 184 109 215 147 146 + 35 92 49 236 163 102 + 137 204 230 250 278 286 + 269 224 238 306 216 255 + 237 173 182 162 147 125 + 162 160 104 114 123 135 + 100000000 192 192 163 193 191 + 223 230 226 144 139 147 + 156 174 184 165 230 215 + 186 249 242 234 252 251 + 267 282 289 332 323 297 + 259 299 325 298 297 325 + 317 113 327 260 198 168 + 225 182 348 237 174 270 + 38 64 84 112 120 103 + 78 92 140 88 135 122 + 78 63 57 94 105 30 + 59 84 146 77 38 87 + 100000000 28 20 47 25 31 + 38 47 110 105 129 122 + 160 142 161 178 136 108 + 96 76 68 86 105 156 + 158 143 187 178 138 93 + 153 179 132 131 160 151 + 147 192 114 156 24 59 + 50 203 130 132 104 151 + 177 197 225 221 216 50 + 64 202 60 107 94 117 + 76 96 133 144 109 138 + 163 208 156 168 217 139 + 100000000 159 19 138 170 177 + 173 240 235 257 245 288 + 255 274 291 249 221 209 + 189 181 199 218 269 271 + 256 282 273 251 206 266 + 284 226 208 177 180 277 + 179 227 269 115 172 102 + 298 243 245 217 89 115 + 135 163 171 154 122 136 + 191 114 161 148 95 80 + 74 111 94 47 48 73 + 135 66 18 67 77 77 + 100000000 91 76 108 115 111 + 90 85 109 102 140 150 + 169 196 181 132 147 127 + 119 137 156 207 209 194 + 238 229 189 144 204 230 + 183 182 211 202 127 233 + 165 164 53 110 67 254 + 181 120 155 132 158 178 + 206 202 197 31 45 183 + 41 88 75 98 57 77 + 114 125 90 119 144 189 + 137 149 198 120 55 140 + 100000000 119 151 158 154 221 + 216 238 226 269 236 255 + 272 230 202 190 170 162 + 180 199 250 252 237 263 + 254 232 187 247 265 207 + 189 158 161 258 160 208 + 250 96 153 83 279 224 + 226 198 13 39 59 87 + 95 78 77 91 115 87 + 134 121 77 62 56 93 + 104 29 58 83 145 76 + 63 112 25 27 45 46 + 100000000 32 39 35 116 130 + 119 107 150 117 136 153 + 111 83 71 51 43 61 + 80 131 133 118 162 153 + 113 68 128 154 107 106 + 135 126 172 167 89 131 + 23 34 49 178 105 107 + 79 38 48 68 96 104 + 87 109 123 124 119 166 + 153 109 94 88 125 136 + 61 90 115 177 108 69 + 118 31 59 51 78 32 + 100000000 7 16 123 136 126 + 114 157 124 143 160 118 + 90 78 58 50 68 87 + 138 140 125 169 160 120 + 75 135 161 114 115 144 + 135 178 176 96 138 55 + 41 81 185 112 114 88 + 31 41 61 89 97 80 + 105 119 117 115 162 149 + 105 90 84 121 132 57 + 86 111 173 104 65 114 + 27 55 47 74 28 7 + 100000000 9 116 132 119 107 + 150 117 136 153 111 83 + 71 51 43 61 80 131 + 133 118 162 153 113 68 + 128 154 107 108 137 128 + 174 169 89 131 51 34 + 77 178 105 107 81 22 + 32 52 80 88 71 112 + 113 108 122 169 156 112 + 97 91 128 139 64 93 + 118 180 111 74 123 36 + 62 56 81 35 16 9 + 100000000 107 141 110 98 141 + 108 127 144 102 74 62 + 42 34 52 71 122 124 + 109 153 144 104 59 119 + 145 98 99 128 119 166 + 160 80 122 58 25 84 + 169 96 98 72 108 134 + 154 182 190 173 141 155 + 210 133 180 167 114 99 + 93 130 113 66 67 92 + 154 85 37 60 96 96 + 19 110 95 127 134 130 + 100000000 46 75 63 106 116 + 135 162 147 93 166 146 + 138 156 175 199 221 213 + 257 248 208 163 223 249 + 202 201 230 221 120 252 + 184 130 72 129 86 273 + 169 81 174 127 153 173 + 201 209 192 160 174 229 + 152 199 186 133 118 112 + 149 132 85 86 111 173 + 104 56 79 115 115 38 + 129 114 146 153 149 19 + 100000000 29 17 60 70 89 + 116 101 47 135 148 157 + 175 137 153 175 175 219 + 210 183 182 185 211 221 + 220 249 240 85 271 146 + 84 91 148 105 235 123 + 35 193 164 190 210 210 + 240 229 197 211 260 189 + 236 223 170 155 149 186 + 169 122 123 148 210 141 + 93 98 152 152 75 166 + 151 183 190 186 56 45 + 100000000 12 31 41 60 87 + 72 42 106 119 190 208 + 108 124 146 146 190 181 + 154 173 156 182 197 229 + 258 249 56 290 117 55 + 128 185 142 206 94 30 + 202 153 179 199 222 235 + 218 186 200 255 178 225 + 212 159 144 138 175 158 + 111 112 137 199 130 82 + 105 141 141 64 155 140 + 172 179 175 45 57 12 + 100000000 43 53 72 99 84 + 30 118 131 183 201 120 + 136 158 158 202 193 166 + 185 168 194 209 241 270 + 261 68 297 129 67 117 + 174 131 218 106 18 214 + 189 175 195 179 209 214 + 261 234 229 253 300 287 + 234 219 213 250 233 186 + 187 212 270 205 157 175 + 216 216 139 230 202 209 + 202 193 120 122 80 92 + 100000000 10 29 56 41 87 + 75 88 159 177 77 93 + 115 115 159 150 123 142 + 125 151 166 198 227 218 + 105 259 86 24 192 168 + 206 175 63 110 171 179 + 165 185 169 199 204 251 + 224 219 243 290 277 224 + 209 203 240 223 176 177 + 202 260 195 147 165 206 + 206 129 220 192 199 192 + 183 110 112 70 82 49 + 100000000 19 46 31 77 65 + 78 149 167 67 83 105 + 105 149 140 113 132 115 + 141 156 188 217 208 95 + 249 76 14 182 158 196 + 165 53 100 161 212 205 + 225 209 239 244 245 259 + 259 237 284 271 218 203 + 197 234 217 170 171 196 + 241 189 141 146 200 200 + 123 214 199 231 232 223 + 104 93 51 63 30 40 + 100000000 67 71 93 105 118 + 189 207 107 104 117 145 + 167 158 153 172 155 181 + 196 228 254 248 76 286 + 116 54 176 198 190 183 + 93 81 201 184 170 190 + 174 204 209 256 229 224 + 248 295 282 229 214 208 + 245 228 181 182 207 269 + 200 152 175 211 211 134 + 225 197 204 197 188 115 + 150 108 106 87 72 57 + 100000000 36 82 70 83 154 + 172 72 37 59 110 109 + 100 118 137 120 146 161 + 193 196 213 133 228 81 + 86 187 163 201 125 58 + 106 166 148 134 154 138 + 168 173 220 193 188 212 + 259 246 193 178 172 209 + 192 145 146 171 233 164 + 116 139 175 175 98 189 + 161 168 161 152 79 125 + 82 70 85 36 55 82 + 100000000 46 34 47 118 136 + 36 87 89 74 118 109 + 82 101 84 110 125 157 + 186 177 131 218 45 50 + 151 127 165 134 22 70 + 130 213 199 219 203 233 + 238 285 258 253 277 324 + 311 258 243 237 274 257 + 210 211 236 294 229 181 + 199 240 240 163 254 226 + 233 226 217 144 146 104 + 116 83 34 53 80 65 + 100000000 99 112 183 201 101 + 117 139 139 183 174 147 + 166 149 175 190 222 251 + 242 129 283 110 48 216 + 192 230 199 87 134 195 + 153 146 166 150 180 185 + 186 200 200 178 225 212 + 159 144 138 175 158 111 + 112 137 199 130 82 105 + 141 141 64 155 140 172 + 173 164 45 91 48 36 + 79 46 65 92 77 12 + 100000000 59 130 148 48 99 + 101 86 130 121 94 113 + 96 122 137 169 198 189 + 104 230 57 60 117 139 + 131 146 34 36 142 173 + 166 186 170 200 205 206 + 220 220 198 245 232 179 + 164 158 195 178 131 132 + 157 219 150 102 125 161 + 161 84 175 160 192 193 + 184 65 111 68 56 99 + 66 85 112 97 32 20 + 100000000 150 168 68 119 121 + 106 150 141 114 133 116 + 142 157 189 218 209 124 + 250 77 80 137 159 151 + 166 54 56 162 30 16 + 36 64 72 55 120 97 + 92 125 172 156 120 105 + 99 136 147 72 101 126 + 188 119 106 133 68 70 + 88 89 43 50 43 34 + 73 119 76 64 107 74 + 93 110 68 40 28 8 + 100000000 18 37 88 90 75 + 119 110 70 25 85 111 + 64 83 112 103 132 144 + 46 88 66 9 92 135 + 62 64 56 54 40 60 + 59 89 79 144 114 109 + 142 189 173 144 129 123 + 160 171 96 125 150 212 + 143 130 157 92 94 112 + 113 67 74 67 58 97 + 143 100 88 131 86 105 + 92 50 64 52 32 24 + 100000000 19 70 72 57 101 + 92 52 7 67 93 46 + 78 107 98 156 139 28 + 100 90 33 116 117 72 + 88 51 112 98 118 102 + 132 137 202 157 152 185 + 232 216 202 187 181 218 + 223 154 177 202 264 195 + 147 170 150 152 129 171 + 125 132 125 116 110 156 + 113 101 116 67 86 73 + 31 77 65 78 82 100 + 100000000 51 53 38 82 73 + 46 65 48 74 89 121 + 150 141 162 182 9 81 + 148 91 174 98 53 101 + 94 178 164 184 168 198 + 203 268 223 218 251 290 + 259 251 236 230 267 250 + 203 204 229 291 222 174 + 197 216 218 156 237 191 + 198 191 182 137 172 130 + 128 109 94 79 22 58 + 104 92 105 148 166 94 + 100000000 34 126 84 75 112 + 131 114 126 155 181 171 + 207 155 203 103 108 209 + 157 223 100 80 128 160 + 144 130 150 134 164 169 + 234 189 184 217 256 225 + 234 219 213 250 261 186 + 215 240 302 233 211 234 + 182 184 193 203 157 164 + 157 148 174 209 167 165 + 146 131 116 59 95 141 + 129 122 114 132 93 96 + 100000000 92 50 41 78 97 + 80 92 121 147 137 173 + 192 169 102 145 180 123 + 206 66 117 165 126 138 + 124 144 128 158 163 228 + 183 178 211 250 219 228 + 213 207 244 255 180 209 + 234 296 227 191 214 176 + 178 173 197 151 158 151 + 142 154 189 147 145 126 + 111 96 39 75 121 109 + 116 108 126 87 17 15 + 100000000 44 35 72 91 74 + 86 115 141 131 167 172 + 163 96 125 174 117 200 + 60 97 145 120 94 80 + 100 84 114 119 184 139 + 134 167 214 198 184 169 + 163 200 211 136 165 190 + 252 183 170 197 132 134 + 152 153 107 114 107 98 + 137 183 140 128 159 110 + 129 81 74 104 92 72 + 64 82 43 59 57 42 + 100000000 62 28 47 30 56 + 71 103 132 123 196 164 + 52 124 130 73 156 16 + 96 128 76 103 89 109 + 93 123 128 193 148 143 + 176 215 184 193 178 172 + 209 220 145 174 199 261 + 192 179 206 141 143 161 + 162 116 123 116 107 146 + 192 149 137 168 119 138 + 90 83 113 101 81 73 + 91 52 68 41 51 9 + 100000000 37 56 39 51 80 + 106 96 132 205 128 61 + 133 139 82 165 25 105 + 137 85 66 52 72 71 + 101 91 156 126 121 154 + 201 185 156 141 135 172 + 183 108 137 162 224 155 + 142 169 104 106 124 125 + 79 86 79 70 109 155 + 112 100 131 82 101 88 + 46 76 64 44 36 54 + 15 66 68 53 97 88 + 100000000 19 63 89 58 90 + 119 110 168 151 24 96 + 102 45 128 113 68 100 + 63 47 33 53 52 82 + 72 137 107 102 135 182 + 166 137 122 116 153 164 + 89 118 143 205 136 123 + 150 85 87 105 106 60 + 67 60 51 90 136 93 + 81 124 91 110 127 85 + 57 45 25 17 35 54 + 105 107 92 136 127 45 + 100000000 102 128 39 71 100 + 91 149 132 63 105 83 + 26 109 152 79 81 44 + 113 99 119 54 84 100 + 187 109 104 137 184 168 + 203 171 182 219 230 155 + 184 209 271 202 189 216 + 151 137 171 156 126 133 + 126 117 156 202 159 147 + 178 129 148 122 93 123 + 111 91 83 101 62 100 + 73 83 41 32 47 66 + 100000000 26 41 73 102 93 + 215 134 71 143 149 92 + 175 57 115 147 46 129 + 124 128 56 86 102 189 + 111 106 139 186 170 214 + 173 193 230 241 171 200 + 225 287 218 205 241 167 + 139 187 158 142 158 151 + 142 181 227 184 172 203 + 154 173 160 118 148 136 + 116 108 126 87 138 140 + 125 168 159 72 91 135 + 100000000 34 75 104 95 240 + 136 96 168 165 117 191 + 184 140 172 48 95 90 + 94 22 52 68 155 77 + 72 105 152 136 180 139 + 159 196 207 137 166 191 + 253 184 171 207 133 105 + 153 124 108 124 117 108 + 147 193 150 138 169 120 + 139 126 84 114 102 82 + 74 92 53 104 106 91 + 134 125 38 57 101 127 + 100000000 41 70 61 206 102 + 62 134 131 83 157 150 + 106 138 14 113 108 112 + 40 70 86 160 56 51 + 84 131 115 159 118 138 + 175 186 151 180 205 250 + 198 189 225 151 123 171 + 129 126 142 135 126 165 + 211 168 156 187 138 157 + 144 102 132 120 100 92 + 110 71 122 124 109 93 + 84 56 75 93 95 18 + 100000000 29 29 224 61 80 + 152 149 101 144 109 124 + 156 32 146 160 145 101 + 103 119 193 89 84 117 + 119 88 190 151 171 208 + 219 184 213 238 283 231 + 222 271 184 156 204 162 + 159 184 177 168 226 272 + 229 217 248 199 218 186 + 163 193 181 161 153 171 + 132 164 137 147 105 96 + 117 136 105 107 79 61 + 100000000 62 285 32 141 213 + 182 162 177 121 185 217 + 93 84 98 83 69 41 + 57 131 27 22 55 102 + 86 130 89 109 146 157 + 122 151 176 221 169 160 + 209 122 94 142 100 97 + 122 115 106 187 227 190 + 178 216 167 186 173 131 + 154 142 122 114 132 100 + 151 153 138 122 113 85 + 104 122 124 47 29 58 + 100000000 246 67 109 181 120 + 105 115 138 153 178 61 + 146 172 192 220 228 211 + 179 193 248 171 218 205 + 152 137 131 168 151 104 + 105 130 192 123 75 80 + 134 134 57 148 133 165 + 172 168 38 27 34 44 + 65 75 76 121 106 74 + 140 153 176 194 142 158 + 180 180 224 215 188 201 + 190 216 231 239 268 259 + 100000000 290 151 89 110 167 + 124 240 128 62 212 114 + 128 113 69 71 87 161 + 57 52 85 120 89 160 + 119 139 176 187 152 181 + 206 251 199 190 239 152 + 124 172 130 127 152 145 + 136 194 240 197 185 216 + 167 186 173 131 161 149 + 129 121 139 100 151 153 + 138 122 113 85 104 122 + 124 47 29 58 30 253 + 100000000 109 181 150 130 145 + 138 153 185 61 103 89 + 109 93 123 128 193 148 + 143 176 223 207 193 178 + 172 209 220 145 174 199 + 261 192 179 206 141 143 + 161 162 116 123 116 107 + 146 192 149 137 153 119 + 123 66 83 113 101 81 + 73 91 52 44 44 29 + 73 64 37 56 39 65 + 80 112 141 132 199 173 + 100000000 133 139 82 165 89 + 105 137 85 165 151 171 + 155 185 190 237 210 205 + 229 276 263 210 195 189 + 226 209 162 163 188 250 + 181 133 156 192 192 115 + 206 178 185 178 169 96 + 132 90 87 69 53 39 + 53 17 63 51 64 135 + 153 53 90 106 91 135 + 126 99 118 101 127 142 + 174 203 194 115 235 62 + 100000000 168 144 182 151 39 + 87 147 36 62 82 110 + 118 101 74 88 138 73 + 120 107 54 39 33 70 + 81 6 35 60 122 53 + 62 111 24 24 44 43 + 23 55 62 58 134 129 + 142 130 173 140 159 176 + 134 106 94 74 66 84 + 103 154 156 141 185 176 + 136 91 151 177 130 129 + 158 149 171 190 112 154 + 100000000 57 26 201 128 130 + 102 21 7 27 55 63 + 46 111 88 83 116 163 + 147 111 96 90 127 138 + 63 92 117 179 110 97 + 142 59 61 79 80 34 + 41 34 25 82 128 85 + 73 116 83 102 119 77 + 49 37 17 9 27 46 + 97 99 84 128 119 79 + 34 94 120 73 74 103 + 94 141 135 55 97 57 + 100000000 83 144 71 73 47 + 102 128 148 176 184 167 + 69 83 203 61 108 95 + 28 27 7 44 55 60 + 89 96 119 107 119 165 + 90 90 110 38 89 121 + 128 124 191 186 208 196 + 239 206 225 242 200 172 + 160 140 132 150 169 220 + 222 207 251 242 202 157 + 217 243 196 195 178 181 + 228 180 178 220 66 123 + 100000000 267 194 196 168 164 + 150 170 154 184 189 254 + 209 204 237 276 245 254 + 239 233 270 281 206 235 + 260 322 253 217 240 202 + 204 199 223 177 184 177 + 168 180 215 173 171 152 + 137 122 65 101 147 135 + 142 134 152 113 43 41 + 26 70 61 98 117 100 + 112 141 167 157 193 198 + 189 122 151 200 143 226 + 100000000 123 171 146 126 112 + 132 116 146 151 216 171 + 166 199 246 230 216 201 + 195 232 237 168 191 216 + 278 209 161 184 164 166 + 143 185 139 146 139 130 + 124 170 127 115 130 81 + 100 87 45 91 79 92 + 96 114 14 65 67 52 + 96 87 60 79 62 88 + 103 135 164 155 176 196 + 23 95 162 105 188 112 + 100000000 115 108 225 211 231 + 215 245 250 297 270 265 + 289 336 323 270 255 249 + 286 269 222 223 248 306 + 241 193 211 252 252 175 + 266 238 245 238 229 156 + 158 116 128 95 46 65 + 92 77 12 111 124 195 + 213 113 129 151 151 195 + 186 159 178 161 187 202 + 234 263 254 141 295 122 + 60 228 204 242 211 99 + 100000000 207 81 95 80 8 + 38 54 141 63 58 91 + 138 122 166 125 145 182 + 193 123 152 177 239 170 + 157 206 119 91 139 110 + 94 119 112 103 184 224 + 187 175 214 165 184 171 + 129 151 139 119 111 129 + 98 149 151 136 120 111 + 83 102 120 122 45 27 + 56 47 243 88 107 179 + 117 102 143 136 151 175 + 0 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/rbg323.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/rbg323.atsp new file mode 100644 index 0000000..c19aa72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/rbg323.atsp @@ -0,0 +1,6467 @@ +NAME: rbg323 +TYPE: ATSP +COMMENT: Stacker crane application (Ascheuer) +DIMENSION: 323 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 0 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 18 0 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 15 10 0 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 20 20 21 0 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 23 23 23 33 0 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 17 14 12 27 16 0 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 18 18 20 18 27 18 0 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 17 10 11 25 23 25 20 0 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 0 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 17 14 15 23 25 23 12 15 24 0 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 21 21 23 15 28 15 11 23 22 16 0 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 1 15 24 21 7 + 15 24 14 11 28 14 18 9 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 22 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 13 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 11 28 24 28 13 18 12 18 23 10 25 5 28 + 18 13 18 23 28 21 20 18 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 18 + 23 21 12 12 11 24 14 28 12 18 24 10 24 23 24 24 15 + 18 24 23 24 12 21 24 28 13 28 18 23 18 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 7 23 28 10 18 13 + 25 12 14 12 13 25 13 25 14 24 11 11 18 23 12 14 24 + 10 24 23 28 16 21 7 21 14 13 10 23 24 12 24 24 1 + 28 18 13 12 27 10 12 10 14 25 16 18 14 14 12 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 0 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 0 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 0 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 0 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 23 23 23 14 29 14 12 23 23 20 11 15 20 20 25 0 27 + 15 16 16 15 18 4 12 27 23 14 14 15 14 20 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 24 15 14 25 23 11 + 18 24 16 12 29 15 10 11 14 14 12 15 30 12 24 27 11 + 14 14 20 23 14 14 23 14 14 12 14 29 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 23 12 14 23 15 + 12 15 23 16 23 16 21 24 14 14 14 14 14 14 14 14 16 + 14 14 26 14 14 14 14 23 26 12 12 26 15 15 15 29 23 + 27 25 24 24 20 25 25 15 16 15 15 15 10 23 15 12 23 + 23 23 23 29 30 24 25 25 15 28 28 25 25 25 23 26 29 + 23 28 25 15 12 29 25 29 0 21 10 11 24 15 26 11 29 + 21 10 4 24 29 23 23 12 15 24 23 25 23 29 15 25 23 + 23 23 24 29 29 15 15 18 28 23 27 21 24 27 15 18 14 + 24 23 15 15 15 25 16 29 15 10 24 12 25 24 25 24 18 + 12 24 24 24 15 23 25 30 10 30 11 24 16 23 28 23 12 + 28 29 25 18 20 12 15 23 23 26 15 11 23 29 10 18 0 + 27 11 12 15 10 26 11 27 15 25 12 15 15 23 15 12 25 + 10 24 24 29 20 23 11 23 15 10 12 23 24 10 25 24 15 + 29 10 11 15 28 12 15 12 15 27 20 10 15 16 15 30 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 0 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 0 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 0 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 0 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 0 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 16 18 20 26 20 10 18 24 12 12 0 12 12 23 11 24 + 18 11 11 16 0 14 18 24 19 20 20 15 20 12 21 23 20 + 20 20 21 20 20 23 20 20 20 16 20 20 12 20 23 23 12 + 12 23 11 10 26 18 19 12 20 20 10 16 27 18 23 24 16 + 20 20 15 18 20 20 24 8 20 11 20 26 20 24 20 20 20 + 20 20 20 20 20 16 20 16 16 20 20 20 15 10 20 18 10 + 11 18 15 11 15 11 14 23 20 20 20 20 20 20 20 20 11 + 20 20 24 20 20 20 20 16 24 11 11 24 10 18 10 26 16 + 24 23 23 21 12 23 23 18 14 12 18 16 15 16 18 18 16 + 18 18 17 26 27 23 23 23 16 25 25 23 23 23 22 24 26 + 16 25 23 18 12 26 23 26 15 19 15 19 21 11 24 12 26 + 14 15 19 21 26 16 15 20 16 23 18 23 15 26 18 23 16 + 23 16 20 26 26 16 10 12 25 16 24 14 23 24 18 12 19 + 20 19 15 10 14 23 11 26 14 19 23 11 23 20 23 23 15 + 20 23 21 23 15 17 23 27 15 27 19 20 19 15 25 16 11 + 25 26 23 12 12 10 16 18 18 24 18 12 18 26 12 19 15 + 24 16 18 16 15 24 15 24 18 23 10 14 19 18 16 18 23 + 12 23 21 26 14 16 12 16 18 15 11 18 23 15 23 23 12 + 26 19 16 15 25 11 15 11 18 24 12 19 18 11 0 27 23 + + 18 18 16 29 15 29 24 16 24 23 25 24 23 23 12 25 0 + 28 23 23 28 23 0 28 10 19 29 29 27 29 23 14 12 29 + 29 29 21 29 29 23 29 29 29 28 29 15 25 29 11 23 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 15 15 28 + 29 29 23 16 29 29 24 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 29 29 29 18 10 25 25 19 24 28 24 12 18 + 15 12 12 14 23 15 19 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 15 12 12 12 22 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 19 25 19 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 23 18 15 12 15 28 24 23 11 18 0 21 12 15 28 23 24 + 15 19 27 24 27 15 23 12 24 27 15 25 12 15 15 12 23 + 29 12 14 12 27 18 15 14 27 14 28 15 23 20 12 18 25 + 15 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 19 28 28 28 26 10 25 19 28 19 24 27 24 16 28 28 11 + 26 12 19 12 23 18 25 18 28 26 25 16 12 27 11 15 25 + 12 27 28 27 15 25 27 25 28 15 23 27 28 23 24 15 11 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 0 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 0 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 0 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 24 14 31 14 16 24 24 23 14 18 23 23 27 15 28 + 15 21 21 15 23 12 0 28 24 0 14 15 14 23 25 26 14 + 14 14 24 14 14 24 14 14 14 15 14 25 15 14 27 24 14 + 23 26 21 16 31 15 12 14 14 14 16 15 31 0 26 28 10 + 14 14 23 24 14 14 24 18 14 16 14 31 14 29 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 24 16 14 24 20 + 15 15 24 21 24 21 23 26 14 14 14 14 14 14 14 14 21 + 14 14 28 14 14 14 14 24 28 15 15 28 20 15 20 31 24 + 29 27 26 25 23 27 27 15 21 15 15 15 12 24 15 9 24 + 24 24 24 31 31 26 27 27 15 30 31 27 27 27 24 28 31 + 24 30 27 15 15 31 27 31 12 23 11 10 25 15 28 14 31 + 23 11 12 25 31 24 24 10 15 26 24 27 24 31 15 27 24 + 24 24 25 31 31 15 20 23 30 24 28 23 26 29 15 23 18 + 25 24 15 20 15 27 21 31 20 11 26 15 27 25 27 26 23 + 10 26 25 26 15 24 27 31 11 31 10 25 21 24 31 24 15 + 31 31 27 23 23 16 15 24 24 28 15 14 24 31 12 23 12 + 28 10 9 15 12 28 14 28 15 27 16 15 20 24 15 0 27 + 12 26 25 31 23 24 14 24 15 12 15 24 26 11 27 26 15 + 31 11 10 15 31 15 15 15 15 28 23 11 15 21 18 31 27 + + 23 23 23 12 29 12 12 23 23 20 11 14 20 20 25 12 27 + 12 16 16 11 18 0 12 27 23 12 0 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 10 11 12 12 12 11 30 12 24 27 11 + 12 12 20 23 12 12 23 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 10 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 4 21 10 11 24 12 26 11 29 + 21 10 9 24 29 23 23 12 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 14 + 24 23 10 15 10 25 16 29 15 10 24 12 25 24 25 24 18 + 12 24 24 24 10 23 25 30 10 30 11 24 16 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 18 4 + 27 11 12 11 10 26 11 27 12 25 12 10 15 23 11 12 25 + 10 24 24 29 20 23 11 23 12 10 12 23 24 10 25 24 11 + 29 10 11 10 28 12 10 12 12 27 20 10 12 16 14 30 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 0 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 12 14 23 24 23 12 14 14 10 15 12 10 10 20 14 23 + 23 10 10 21 0 18 23 23 12 23 23 20 0 10 16 18 23 + 23 23 12 23 23 12 23 23 23 21 23 15 15 23 21 12 15 + 4 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 14 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 12 23 24 + 12 24 20 23 14 24 20 24 18 11 20 21 16 14 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 12 24 23 21 12 + 12 12 15 24 24 21 11 3 24 12 23 11 18 23 23 10 12 + 15 12 20 11 18 21 10 24 11 20 18 14 20 15 21 18 4 + 23 18 16 18 20 12 20 25 20 25 21 15 10 12 24 12 14 + 24 24 21 10 10 12 21 14 14 23 23 15 14 24 16 9 18 + 23 21 23 21 16 23 15 23 23 21 12 18 11 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 0 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 12 12 12 27 18 27 23 12 12 16 24 23 16 16 15 23 15 + 26 20 20 25 18 24 26 12 12 27 27 25 27 16 0 9 27 + 27 27 12 27 27 12 27 27 27 25 27 15 24 27 15 12 24 + 18 9 20 23 18 26 24 24 27 27 23 25 20 26 0 12 25 + 27 27 16 12 27 27 12 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 15 23 27 12 21 + 23 26 14 20 14 20 15 9 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 15 23 23 12 21 26 21 18 12 + 14 15 15 15 16 11 11 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 15 10 10 25 15 16 10 10 15 12 15 18 + 15 15 10 26 23 18 10 18 24 15 25 25 10 23 12 24 18 + 15 25 24 15 18 12 14 27 25 15 12 15 15 18 26 11 12 + 12 15 15 18 18 25 21 18 15 15 15 15 15 14 26 18 23 + 15 12 25 21 24 11 20 18 21 25 0 23 10 11 11 9 18 + 27 15 15 9 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 15 18 16 23 25 12 12 15 26 24 12 18 24 18 24 + 12 25 26 25 24 15 24 12 26 11 23 24 21 12 25 26 15 + 24 15 10 18 16 12 24 12 26 24 23 12 15 25 15 0 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 0 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 0 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 11 0 10 24 23 24 18 10 18 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 14 24 24 23 24 12 12 12 24 + 0 24 15 24 24 17 24 24 24 24 24 11 21 24 15 17 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 18 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 1 24 24 4 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 0 16 20 20 16 15 24 15 23 3 + 20 14 12 12 12 15 15 24 14 23 24 24 23 10 24 24 0 + 10 10 11 23 23 12 14 14 24 21 23 14 14 14 16 16 23 + 5 21 14 24 20 23 14 23 23 14 23 24 12 20 16 21 23 + 11 23 23 12 23 4 10 24 24 12 10 14 10 23 24 15 7 + 17 5 11 23 23 24 15 12 21 5 18 11 12 20 24 12 16 + 11 14 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 11 14 23 23 23 24 11 14 10 23 9 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 14 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 14 23 12 3 21 1 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 14 2 10 24 23 24 18 10 21 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 16 24 24 23 24 12 12 12 24 + 24 0 18 24 24 20 24 24 24 24 24 11 21 24 15 20 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 21 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 7 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 6 + 20 14 12 12 12 15 16 24 14 23 24 24 23 13 24 24 2 + 10 10 14 23 23 12 14 14 24 21 23 14 14 14 19 16 23 + 3 21 14 24 20 23 14 23 23 16 23 24 12 20 16 21 23 + 11 23 23 12 23 7 12 24 24 12 10 14 10 23 24 15 9 + 20 3 11 23 23 24 15 12 21 3 18 11 12 20 24 12 16 + 11 16 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 14 14 23 23 23 24 11 16 10 23 12 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 16 23 + 18 24 24 24 23 16 21 18 24 16 18 23 16 10 24 24 15 + 23 12 16 23 12 6 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 0 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 14 15 23 25 23 12 15 17 11 14 11 11 11 21 12 23 + 21 0 4 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 0 23 16 23 23 23 20 23 16 14 23 23 16 14 + 10 20 1 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 17 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 1 12 1 12 20 23 23 23 23 23 23 23 23 4 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 7 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 15 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 16 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 12 + 16 14 18 10 16 23 4 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 12 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 12 16 + 23 20 21 20 15 23 14 23 21 23 12 16 12 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 6 11 25 23 + + 10 10 4 25 23 25 20 6 17 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 12 25 25 24 25 12 11 12 25 + 25 25 14 25 0 16 25 25 25 24 25 10 23 25 14 16 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 3 25 25 17 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 3 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 11 12 14 14 24 15 23 24 24 23 10 24 24 10 + 1 2 10 23 23 12 12 12 24 20 21 12 12 12 15 15 23 + 10 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 11 23 10 11 25 24 12 3 12 11 23 24 14 10 + 16 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 12 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 2 0 15 24 23 1 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 1 24 24 14 + 23 12 12 23 12 10 23 10 24 23 21 2 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 0 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 10 10 0 25 23 25 20 1 12 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 11 12 25 + 25 25 10 25 25 11 0 25 25 24 25 11 23 25 14 11 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 1 25 25 12 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 1 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 11 12 14 14 24 15 23 24 24 23 10 24 24 10 + 6 2 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 11 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 11 23 10 11 25 24 12 1 12 11 23 24 14 10 + 11 11 11 23 23 24 16 14 20 11 16 12 12 18 24 14 18 + 11 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 2 4 15 24 23 6 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 3 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 2 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 9 2 10 24 23 24 18 10 16 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 11 24 24 23 24 12 12 12 24 + 24 24 12 24 24 15 24 0 24 24 24 11 21 24 15 15 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 16 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 1 24 24 2 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 1 + 20 14 12 12 12 15 15 24 14 23 24 24 23 8 24 24 2 + 10 10 9 23 23 12 14 14 24 21 23 14 14 14 14 16 23 + 8 21 14 24 20 23 14 23 23 11 23 24 12 20 16 21 23 + 11 23 23 12 23 2 10 24 24 12 10 14 10 23 24 15 4 + 15 8 11 23 23 24 15 12 21 8 18 11 12 20 24 12 16 + 11 11 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 9 14 23 23 23 24 11 14 10 23 7 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 12 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 12 23 12 1 21 1 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 10 10 1 25 23 25 20 0 11 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 12 12 25 + 25 25 10 25 25 10 25 25 0 24 25 12 23 25 14 10 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 2 25 25 11 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 12 20 25 2 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 12 12 14 14 24 15 23 24 24 23 10 24 24 10 + 7 3 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 12 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 12 23 10 11 25 24 12 2 12 12 23 24 14 10 + 10 12 12 23 23 24 16 14 20 12 16 12 12 18 24 14 18 + 12 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 12 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 3 6 15 24 23 7 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 4 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 3 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 0 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 10 10 1 25 23 25 20 0 11 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 12 12 25 + 25 25 10 25 25 10 25 25 25 24 0 12 23 25 14 10 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 2 25 25 11 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 12 20 25 2 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 12 12 14 14 24 15 23 24 24 23 10 24 24 10 + 7 3 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 12 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 12 23 10 11 25 24 12 2 12 12 23 24 14 10 + 10 12 12 23 23 24 16 14 20 12 16 12 12 18 24 14 18 + 12 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 12 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 3 6 15 24 23 7 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 4 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 3 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 0 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 0 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 6 4 10 24 23 24 18 10 13 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 9 24 24 23 24 12 12 12 24 + 24 24 10 24 24 12 24 24 24 24 24 11 21 0 15 12 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 13 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 0 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 4 16 20 20 16 15 24 15 23 1 + 20 14 12 12 12 15 15 24 14 23 24 24 23 5 24 24 4 + 10 10 6 23 23 12 14 14 24 21 23 14 14 14 11 16 23 + 10 21 14 24 20 23 14 23 23 11 23 24 12 20 16 21 23 + 11 23 23 12 23 0 10 24 24 12 10 14 10 23 24 15 2 + 12 10 11 23 23 24 15 12 21 10 18 11 12 20 24 12 16 + 11 9 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 6 14 23 23 23 24 11 14 10 23 4 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 12 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 12 23 12 1 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 0 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 0 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 21 21 23 15 28 15 11 23 22 16 10 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 1 15 24 21 0 + 15 24 14 11 28 14 18 9 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 22 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 13 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 11 28 24 28 13 18 12 18 23 10 25 5 28 + 18 13 18 23 28 21 20 18 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 18 + 23 21 12 12 11 24 14 28 12 18 24 10 24 23 24 24 15 + 18 24 23 24 12 21 24 28 13 28 18 23 18 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 7 23 28 10 18 13 + 25 12 14 12 13 25 13 25 14 24 11 11 18 23 12 14 24 + 10 24 23 28 16 21 7 21 14 13 10 23 24 12 24 24 1 + 28 18 13 12 27 10 12 10 14 25 16 18 14 14 12 28 24 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 0 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 0 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 12 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 0 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 0 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 0 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 14 31 14 16 24 24 23 14 18 23 23 27 15 28 + 15 21 21 15 23 12 0 28 24 14 14 15 14 23 25 26 14 + 14 14 24 14 14 24 14 14 14 15 14 25 15 14 27 24 14 + 23 26 21 16 31 0 12 14 14 14 16 15 31 0 26 28 10 + 14 14 23 24 14 14 24 18 14 16 14 31 14 29 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 24 16 14 24 20 + 15 15 24 21 24 21 23 26 14 14 14 14 14 14 14 14 21 + 14 14 28 14 14 14 14 24 28 15 15 28 20 15 20 31 24 + 29 27 26 25 23 27 27 15 21 15 15 15 12 24 15 9 24 + 24 24 24 31 31 26 27 27 15 30 31 27 27 27 24 28 31 + 24 30 27 15 15 31 27 31 12 23 11 10 25 15 28 14 31 + 23 11 12 25 31 24 24 10 15 26 24 27 24 31 15 27 24 + 24 24 25 31 31 15 20 23 30 24 28 23 26 29 15 23 18 + 25 24 15 20 15 27 21 31 20 11 26 15 27 25 27 26 23 + 10 26 25 26 15 24 27 31 11 31 10 25 21 24 31 24 15 + 31 31 27 23 23 16 15 24 24 28 15 14 24 31 12 23 12 + 28 10 9 15 12 28 14 28 15 27 16 15 20 24 15 0 27 + 12 26 25 31 23 24 14 24 15 12 15 24 26 11 27 26 15 + 31 11 10 15 31 15 15 15 15 28 23 11 15 21 18 31 27 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 0 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 0 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 21 21 23 15 28 15 11 23 21 16 2 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 9 15 24 21 0 + 15 24 14 11 28 14 10 1 0 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 2 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 0 23 28 10 15 11 + 25 12 14 12 10 25 5 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 0 21 14 10 10 23 24 12 24 24 9 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 14 14 12 27 16 27 23 12 17 18 24 23 18 18 6 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 16 27 27 27 26 27 12 24 27 10 16 24 + 20 10 21 23 16 27 24 24 27 0 23 26 18 27 10 12 26 + 27 27 18 12 27 27 17 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 12 23 27 23 16 14 + 12 6 10 11 18 10 12 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 3 3 26 14 15 6 3 6 15 11 16 + 14 14 1 27 24 16 6 16 25 16 25 26 11 24 12 24 16 + 16 25 25 11 16 14 15 27 26 10 12 6 15 16 27 10 14 + 16 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 3 12 10 10 20 + 27 10 11 10 25 14 8 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 12 23 25 23 12 26 27 10 + 24 10 12 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 15 16 21 25 21 11 16 22 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 18 21 21 16 21 12 20 21 21 + 21 21 19 21 21 21 21 21 21 18 21 18 12 21 23 21 12 + 11 21 10 11 25 20 18 12 21 21 0 18 26 20 21 24 18 + 21 21 13 16 21 21 22 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 5 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 5 20 6 25 15 + 24 23 21 20 12 23 23 20 12 14 20 18 14 15 20 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 20 23 25 + 15 24 23 20 12 25 23 25 15 18 16 18 20 12 23 12 25 + 12 16 18 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 21 15 18 25 25 18 6 11 24 15 24 12 21 24 20 11 18 + 18 18 16 4 15 23 10 25 12 18 21 12 23 18 23 21 13 + 21 21 20 21 16 15 23 26 16 26 18 18 18 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 18 15 + 24 18 20 18 14 23 13 24 20 23 11 15 18 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 18 18 16 25 12 16 12 20 24 12 18 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 0 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 0 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 0 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 0 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 23 24 23 24 10 19 12 20 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 0 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 0 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 14 14 12 27 16 27 23 12 17 18 24 23 18 18 6 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 16 27 27 27 26 27 12 24 27 10 16 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 0 27 18 12 27 27 17 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 12 23 27 23 16 14 + 12 6 10 11 18 10 12 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 3 3 26 14 15 6 3 6 15 11 16 + 14 14 1 27 24 16 6 16 25 16 25 26 11 24 12 24 16 + 16 25 25 11 16 14 15 27 26 10 12 6 15 16 27 10 14 + 16 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 3 12 10 10 20 + 27 10 11 10 25 14 8 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 12 23 25 23 12 26 27 10 + 24 10 12 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 21 21 23 15 28 15 11 23 21 16 0 12 16 16 24 11 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 11 15 24 21 2 + 15 24 14 11 28 14 10 1 15 15 11 12 28 14 24 25 12 + 15 0 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 11 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 11 25 4 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 2 23 28 10 15 11 + 25 12 14 12 10 25 3 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 2 21 14 10 10 23 24 12 24 24 11 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 0 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 0 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 21 21 23 15 28 15 11 23 21 16 2 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 9 15 24 21 0 + 15 24 14 11 28 14 10 1 15 15 11 12 28 14 24 25 12 + 15 15 16 23 0 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 2 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 0 23 28 10 15 11 + 25 12 14 12 10 25 5 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 0 21 14 10 10 23 24 12 24 24 9 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 21 21 23 15 28 15 11 23 21 16 1 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 10 15 24 21 1 + 15 24 14 11 28 14 10 0 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 0 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 3 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 1 23 28 10 15 11 + 25 12 14 12 10 25 4 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 1 21 14 10 10 23 24 12 24 24 10 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 0 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 0 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 14 14 12 27 16 27 23 12 15 18 24 23 18 18 9 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 14 27 27 27 26 27 12 24 27 10 14 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 15 23 0 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 9 10 11 18 10 10 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 1 1 26 14 15 3 1 9 14 11 16 + 14 14 3 27 24 16 3 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 9 15 16 27 10 14 + 14 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 1 12 10 10 20 + 27 10 11 10 25 14 5 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 10 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 0 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 14 14 12 27 16 27 23 12 16 18 24 23 18 18 8 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 15 27 27 27 26 27 12 24 27 10 15 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 16 23 27 23 0 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 8 10 11 18 10 11 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 2 2 26 14 15 4 2 8 14 11 16 + 14 14 2 27 24 16 4 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 8 15 16 27 10 14 + 15 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 2 12 10 10 20 + 27 10 11 10 25 14 7 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 11 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 0 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 14 14 15 23 25 23 12 15 16 11 14 11 11 11 21 12 23 + 21 1 3 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 23 23 15 23 23 23 20 23 16 14 23 23 15 14 + 10 20 0 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 16 11 23 12 23 25 0 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 0 12 2 12 20 23 23 23 23 23 23 23 23 3 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 6 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 15 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 11 + 16 14 18 10 16 23 3 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 11 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 11 16 + 23 20 21 20 15 23 14 23 21 23 12 16 11 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 8 11 25 23 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 0 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 18 18 20 18 27 18 9 20 24 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 19 18 18 14 18 14 23 23 18 + 18 18 21 18 18 23 18 18 18 15 18 21 11 18 24 23 11 + 12 23 12 6 27 16 19 11 18 18 5 15 27 16 23 24 15 + 18 18 15 20 18 18 24 10 18 11 18 27 18 25 0 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 9 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 14 12 16 15 15 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 22 24 27 + 18 25 23 16 12 27 23 27 15 19 14 19 23 10 24 11 27 + 15 15 19 23 27 18 16 19 15 23 20 23 16 27 16 24 18 + 23 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 19 + 21 19 14 11 12 24 12 27 14 19 23 10 23 21 24 23 15 + 19 23 23 23 14 18 23 27 15 27 19 21 19 16 26 18 10 + 26 27 24 12 14 10 15 20 20 24 16 11 20 27 12 19 15 + 24 15 16 15 15 24 15 24 16 24 9 12 19 20 15 16 24 + 12 23 23 27 14 18 11 18 16 15 10 20 23 14 24 23 11 + 27 19 15 14 26 10 14 10 16 24 14 19 16 12 10 27 24 + + 11 11 12 24 24 24 15 12 14 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 11 24 24 23 24 10 14 15 24 + 24 24 11 24 24 12 24 24 24 23 24 12 18 24 18 12 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 10 12 24 24 14 14 24 15 24 24 24 23 24 0 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 10 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 18 23 12 20 23 23 20 11 23 23 11 + 12 12 11 24 24 15 16 16 23 23 23 16 16 16 11 20 24 + 11 23 16 23 16 24 16 24 21 9 23 23 14 16 20 18 24 + 0 23 21 14 24 11 10 24 23 15 12 16 10 24 23 18 11 + 12 11 12 24 24 23 12 11 23 11 21 10 15 23 23 11 14 + 12 11 23 12 21 18 12 24 12 23 15 16 16 12 18 15 11 + 24 15 14 15 23 11 16 24 23 24 23 12 12 10 23 11 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 11 21 + 21 23 23 23 20 20 18 21 23 18 15 21 12 12 23 23 18 + 20 15 14 24 10 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 0 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 6 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 0 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 14 14 15 23 25 23 12 15 14 11 14 11 11 11 21 12 23 + 21 4 0 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 23 23 14 23 23 23 20 23 16 14 23 23 14 14 + 10 20 3 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 14 11 23 12 23 25 23 24 23 23 23 + 23 0 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 3 12 6 12 20 23 23 23 23 23 23 23 23 0 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 2 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 14 14 16 25 25 20 10 10 24 14 23 12 20 24 21 11 11 + 16 14 18 10 16 23 0 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 8 12 24 14 12 + 24 25 23 11 11 12 20 15 15 23 21 14 15 25 15 10 16 + 23 20 21 20 15 23 14 23 21 23 12 16 10 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 11 11 25 23 + + 14 14 12 27 16 27 23 12 15 18 24 23 18 18 9 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 14 27 27 27 26 27 12 24 27 10 14 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 15 23 27 23 27 16 27 12 27 27 27 + 27 27 0 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 9 10 11 18 10 10 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 1 1 26 14 15 3 1 9 14 11 16 + 14 14 3 27 24 16 3 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 9 15 16 27 10 14 + 14 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 1 12 10 10 20 + 27 10 11 10 25 14 5 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 10 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 18 18 20 18 27 18 2 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 0 27 16 12 11 18 18 1 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 4 18 27 18 25 18 18 18 + 18 18 18 0 18 18 18 15 18 18 18 18 16 2 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 12 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 3 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 2 12 12 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 12 12 14 23 24 23 12 14 18 10 15 12 10 10 20 14 23 + 23 10 10 21 4 18 23 23 14 23 23 20 23 10 16 18 23 + 23 23 15 23 23 17 23 23 23 21 23 15 15 23 21 17 15 + 0 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 18 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 0 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 16 23 24 + 12 24 20 23 14 24 20 24 18 14 20 21 16 14 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 12 24 23 21 12 + 17 12 15 24 24 21 11 1 24 12 23 11 18 23 23 5 14 + 15 14 20 11 18 21 10 24 11 20 18 14 20 15 21 18 9 + 23 18 16 18 20 12 20 25 20 25 21 15 14 12 24 12 14 + 24 24 21 5 10 12 21 14 14 23 23 15 14 24 16 14 18 + 23 21 23 21 16 23 15 23 23 21 12 18 14 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 0 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 0 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 0 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 0 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 18 18 20 18 27 18 3 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 1 27 16 14 11 18 18 0 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 6 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 0 18 18 16 3 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 14 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 14 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 14 16 26 18 10 + 26 27 24 12 14 4 15 20 20 24 16 11 20 27 12 14 12 + 24 15 16 15 12 24 11 24 16 24 3 12 14 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 0 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 0 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 0 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 0 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 15 15 14 28 15 28 24 14 16 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 15 28 28 28 27 28 12 24 28 8 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 16 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 0 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 11 23 27 23 15 15 + 12 10 11 12 20 7 11 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 11 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 2 15 + 15 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 7 23 15 23 26 11 24 10 12 7 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 8 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 11 27 27 27 25 10 24 11 27 11 24 25 23 14 27 27 8 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 8 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 2 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 0 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 15 15 16 21 25 21 11 16 21 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 16 21 21 16 21 12 20 21 21 + 21 21 18 21 21 20 21 21 21 18 21 18 12 21 23 20 12 + 11 21 10 11 25 20 16 12 21 21 11 18 26 20 21 24 18 + 21 21 12 16 21 21 21 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 0 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 3 20 5 25 15 + 24 23 21 20 12 23 23 20 11 14 20 18 14 15 20 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 19 23 25 + 15 24 23 20 12 25 23 25 15 16 16 18 20 12 23 12 25 + 12 16 16 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 20 15 18 25 25 18 5 11 24 15 24 12 21 24 20 11 16 + 18 16 16 2 15 23 10 25 11 16 21 12 23 18 23 21 12 + 21 21 20 21 16 15 23 26 16 26 18 18 16 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 16 15 + 24 18 20 18 14 23 12 24 20 23 11 15 16 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 16 18 16 25 12 16 12 20 24 12 16 20 10 10 26 23 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 0 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 5 15 23 11 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 0 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 0 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 10 11 24 23 24 16 12 24 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 19 24 24 23 24 11 12 14 24 + 24 24 21 24 24 23 24 24 24 23 24 12 20 24 16 23 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 15 20 23 + 24 24 15 11 24 24 24 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 0 16 24 11 14 + 18 24 10 0 10 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 19 14 24 14 23 10 + 21 15 14 12 11 16 19 24 14 21 24 23 21 16 24 24 10 + 11 11 17 23 24 14 15 15 23 23 23 15 15 15 22 18 23 + 10 23 15 24 18 23 15 23 23 19 23 23 12 18 19 20 23 + 10 23 23 12 23 10 15 24 23 14 11 15 0 23 24 16 12 + 23 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 19 + 12 19 23 14 23 16 12 23 14 23 15 18 15 12 16 14 15 + 24 14 12 14 23 17 15 24 23 24 23 12 19 6 23 15 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 19 23 + 20 23 24 23 21 18 20 20 24 19 16 23 19 11 23 24 16 + 21 14 19 23 14 10 20 10 24 21 18 11 14 23 16 15 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 0 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 0 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 10 10 11 24 23 24 16 11 14 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 10 24 24 23 24 11 12 14 24 + 24 24 10 24 24 12 24 24 24 23 24 12 20 24 16 12 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 14 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 10 16 24 11 14 + 18 24 0 12 0 12 0 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 10 23 24 14 15 15 23 23 23 15 15 15 11 18 23 + 10 23 15 24 18 23 15 23 23 10 23 23 12 18 18 20 23 + 10 23 23 12 23 10 4 24 23 14 11 15 10 23 24 16 10 + 12 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 10 23 14 23 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 10 15 24 23 24 23 12 12 4 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 12 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 12 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 0 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 12 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 6 21 11 10 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 6 11 24 12 11 27 24 12 + 21 25 20 15 31 10 13 12 11 11 15 6 31 10 25 28 0 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 6 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 0 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 6 12 24 10 10 24 + 24 24 24 31 31 25 26 26 6 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 11 23 10 13 25 14 27 12 31 + 23 10 13 25 31 24 23 13 6 25 24 26 23 31 10 27 24 + 24 24 24 31 31 6 18 21 29 24 28 23 25 28 10 21 16 + 24 24 10 18 11 27 20 31 18 13 25 14 26 24 27 25 21 + 13 25 25 25 10 24 26 31 10 31 13 24 20 23 30 24 14 + 30 31 27 21 23 15 6 24 24 27 10 12 24 31 12 21 11 + 28 4 10 6 12 27 12 28 10 27 15 11 18 24 6 10 27 + 12 25 25 31 23 24 12 24 10 12 14 24 25 10 27 25 12 + 31 13 9 10 30 14 10 14 10 28 23 13 10 20 16 31 27 + + 23 23 23 18 28 18 12 23 23 18 10 19 18 18 24 19 26 + 19 15 15 19 16 10 12 26 23 18 18 19 18 18 24 24 18 + 18 18 23 18 18 23 18 18 18 19 18 23 19 18 25 23 10 + 16 24 15 12 28 19 0 10 18 18 14 19 29 12 24 26 13 + 18 18 18 23 18 18 23 12 18 12 18 28 18 27 18 18 18 + 18 18 18 18 18 23 18 19 23 18 18 18 21 12 18 23 14 + 12 19 21 15 21 15 20 24 18 0 18 18 18 18 18 18 15 + 18 18 25 18 18 18 18 23 25 14 11 25 14 19 14 28 23 + 27 24 24 24 18 25 25 19 15 19 19 19 4 23 19 13 23 + 23 23 23 28 29 24 24 24 19 27 28 24 24 24 23 25 28 + 23 27 24 19 11 28 24 28 10 20 11 12 24 19 25 12 28 + 20 11 10 24 28 23 21 14 19 24 23 24 21 28 19 25 23 + 23 23 23 28 28 19 14 16 27 23 26 20 24 27 19 19 12 + 23 23 19 14 19 25 15 28 14 11 24 13 24 23 25 24 16 + 14 24 24 24 19 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 19 18 12 19 23 23 25 19 10 23 28 9 16 10 + 26 12 13 19 4 25 10 26 19 25 12 19 14 23 19 12 25 + 13 24 24 28 18 23 10 23 19 4 11 23 24 13 25 24 19 + 28 11 12 19 28 11 19 13 19 26 19 11 19 19 19 29 25 + + 12 12 12 23 24 23 14 12 12 9 16 15 8 8 18 15 23 + 23 11 11 23 10 20 23 23 12 23 23 21 23 4 15 16 23 + 23 23 12 23 23 12 23 23 23 23 23 15 16 23 20 12 16 + 10 16 11 14 24 23 18 16 23 23 14 23 24 23 16 23 23 + 23 23 0 12 23 23 12 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 15 14 23 12 12 + 15 23 11 11 11 11 15 16 23 23 0 23 23 23 23 23 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 4 20 20 23 11 18 23 23 18 12 23 23 12 + 12 12 12 24 24 16 18 18 23 23 24 18 18 18 12 21 24 + 15 23 18 23 15 24 18 24 20 10 21 23 15 15 21 16 24 + 10 21 20 15 24 12 11 23 23 16 12 18 15 24 23 20 12 + 12 15 15 24 24 23 12 10 23 15 23 15 16 23 23 15 12 + 15 12 21 12 20 20 11 24 12 21 16 15 18 14 20 16 10 + 23 16 15 16 21 12 18 24 21 24 23 14 11 11 24 12 15 + 24 24 20 15 9 14 23 12 12 21 23 16 12 24 18 10 20 + 23 23 23 23 18 21 16 23 23 20 14 20 12 12 23 23 20 + 18 16 15 24 0 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 15 21 23 15 15 24 20 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 0 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 6 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 12 12 12 27 18 27 23 12 12 16 24 23 16 16 15 23 15 + 26 20 20 25 18 24 26 12 12 27 27 25 27 16 15 9 27 + 27 27 12 27 27 12 27 27 27 25 27 15 24 27 15 12 24 + 18 9 20 23 18 26 24 24 27 27 23 25 20 26 0 12 25 + 27 27 16 12 27 27 12 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 15 23 27 12 21 + 23 26 14 20 14 20 15 9 27 27 27 27 0 27 27 27 20 + 27 27 12 27 27 27 27 12 15 23 23 12 21 26 21 18 12 + 14 15 15 15 16 11 11 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 15 10 10 25 15 16 10 10 15 12 15 18 + 15 15 10 26 23 18 10 18 24 15 25 25 10 23 12 24 18 + 15 25 24 15 18 12 14 27 25 15 12 15 15 18 26 11 12 + 12 15 15 18 18 25 21 18 15 15 15 15 15 14 26 18 23 + 15 12 25 21 24 11 20 18 21 25 0 23 10 11 11 9 18 + 27 15 15 9 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 15 18 16 23 25 12 12 15 26 24 12 18 24 18 24 + 12 25 26 25 24 15 24 12 26 11 23 24 21 12 25 26 15 + 24 15 10 18 16 12 24 12 26 24 23 12 15 25 15 0 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 18 18 20 18 27 18 2 20 18 14 11 11 14 14 23 11 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 4 27 16 12 11 18 18 6 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 0 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 2 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 0 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 11 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 10 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 1 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 2 12 11 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 11 27 24 + + 21 21 23 15 28 15 11 23 21 16 1 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 10 15 24 21 1 + 15 24 14 11 28 14 10 0 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 0 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 3 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 1 23 28 10 15 11 + 25 12 14 12 10 25 4 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 1 21 14 10 10 23 24 12 24 24 10 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 12 12 12 23 24 23 14 12 18 0 16 12 1 1 18 15 23 + 23 11 11 23 10 20 23 23 14 23 23 21 23 4 15 16 23 + 23 23 15 23 23 17 23 23 23 23 23 14 16 23 20 17 16 + 10 16 11 14 24 23 18 16 23 23 14 23 24 23 16 23 23 + 23 23 9 12 23 23 18 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 11 14 23 12 12 + 15 23 11 11 11 11 10 16 23 23 23 23 23 23 23 0 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 4 20 20 23 11 18 23 23 18 12 23 23 12 + 12 12 12 24 24 16 18 18 23 23 24 18 18 18 16 21 24 + 12 23 18 23 15 24 18 24 20 14 21 23 15 15 21 16 24 + 10 21 20 15 24 12 11 23 23 16 12 18 11 24 23 20 12 + 17 12 14 24 24 23 12 10 23 12 23 10 16 23 23 10 14 + 14 14 21 12 20 20 11 24 12 21 16 15 18 14 20 16 10 + 23 16 15 16 21 12 18 24 21 24 23 14 14 11 24 12 15 + 24 24 20 10 0 14 23 12 12 21 23 16 12 24 18 14 20 + 23 23 23 23 18 21 16 23 23 20 14 20 14 12 23 23 20 + 18 16 15 24 8 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 5 21 23 11 12 24 20 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 0 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 10 10 11 24 23 24 16 11 14 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 10 24 24 23 24 11 12 14 24 + 24 24 10 24 24 12 24 24 24 23 24 12 20 24 16 12 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 14 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 10 16 24 11 14 + 18 24 0 12 0 12 10 14 24 24 24 24 24 24 24 24 12 + 0 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 10 23 24 14 15 15 23 23 23 15 15 15 11 18 23 + 10 23 15 24 18 23 15 23 23 10 23 23 12 18 18 20 23 + 10 23 23 12 23 10 4 24 23 14 11 15 10 23 24 16 10 + 12 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 10 23 14 23 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 10 15 24 23 24 23 12 12 4 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 12 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 12 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 16 16 15 28 14 28 24 15 16 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 16 28 28 27 28 21 12 12 28 + 28 28 16 28 28 16 28 28 28 27 28 14 25 28 10 16 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 12 10 27 + 28 28 21 15 28 28 16 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 0 4 28 28 28 28 16 10 24 24 9 23 28 23 14 16 + 11 11 12 12 21 10 10 28 23 25 28 27 25 16 28 28 16 + 15 15 16 14 15 12 11 11 27 12 12 11 11 11 16 10 14 + 16 12 11 28 24 14 11 14 26 20 27 27 12 24 9 25 14 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 16 16 14 14 14 27 23 23 12 16 10 20 12 11 28 23 24 + 14 16 27 23 26 10 23 14 23 27 12 24 11 14 10 12 23 + 28 12 12 12 27 16 11 15 27 15 27 14 23 18 12 16 24 + 12 14 10 23 21 24 27 15 15 10 28 25 15 14 25 23 26 + 10 27 28 27 25 10 25 10 28 10 24 26 23 15 27 28 10 + 25 12 12 14 21 16 25 16 28 25 24 15 12 27 10 12 25 + 14 27 27 27 12 24 27 24 28 10 21 27 28 23 24 15 10 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 0 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 12 25 6 + 28 23 23 28 23 27 28 4 18 29 29 27 29 23 14 12 29 + 29 29 18 29 29 18 29 29 29 28 29 15 25 29 11 18 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 12 9 28 + 29 29 23 16 29 29 18 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 0 29 29 29 18 10 25 25 13 24 28 24 12 18 + 10 12 12 14 23 11 13 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 12 12 12 12 18 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 13 25 13 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 18 18 15 12 12 28 24 23 11 18 6 21 12 10 28 23 24 + 15 18 27 24 27 11 23 12 24 27 12 25 12 15 11 12 23 + 29 12 14 12 27 18 12 14 27 14 28 15 23 20 12 18 25 + 12 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 13 28 28 28 26 10 25 13 28 13 24 27 24 16 28 28 11 + 26 12 14 12 23 18 25 18 28 26 25 16 12 27 11 12 25 + 12 27 28 27 12 25 27 25 28 9 23 27 28 23 24 14 11 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 12 25 10 + 28 23 23 28 23 27 28 0 18 29 29 27 29 23 14 12 29 + 29 29 18 29 29 18 29 29 29 28 29 15 25 29 11 18 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 12 4 28 + 29 29 23 16 29 29 18 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 0 29 29 18 10 25 25 10 24 28 24 12 18 + 10 12 12 14 23 11 11 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 12 12 12 12 18 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 10 25 12 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 18 18 15 12 12 28 24 23 11 18 10 21 12 10 28 23 24 + 15 18 27 24 27 11 23 12 24 27 12 25 12 15 11 12 23 + 29 12 14 12 27 18 12 14 27 14 28 15 23 20 12 18 25 + 12 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 9 28 28 28 26 10 25 9 28 11 24 27 24 16 28 28 11 + 26 12 14 12 23 18 25 18 28 26 25 16 12 27 11 12 25 + 12 27 28 27 12 25 27 25 28 4 23 27 28 23 24 14 11 + + 18 18 20 18 27 18 0 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 2 27 16 12 11 18 18 3 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 2 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 0 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 0 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 10 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 1 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 0 12 11 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 19 25 19 + 28 23 23 28 23 27 28 9 18 29 29 27 29 23 19 13 29 + 29 29 18 29 29 18 29 29 29 28 29 19 25 29 19 18 25 + 23 13 23 24 19 28 26 25 29 29 24 28 14 28 12 4 28 + 29 29 23 16 29 29 18 24 29 24 29 19 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 13 29 29 29 29 29 29 29 29 23 + 29 29 13 29 29 29 0 18 19 25 25 10 24 28 24 19 18 + 10 19 19 19 23 11 11 28 23 26 28 28 26 18 28 28 18 + 16 16 18 19 14 19 12 12 28 19 12 12 12 19 18 19 19 + 19 14 14 28 25 19 12 19 27 21 27 28 14 25 10 25 12 + 21 27 27 19 19 18 20 29 28 19 16 19 20 19 28 14 18 + 18 19 19 19 12 28 24 23 19 19 19 21 19 10 28 23 24 + 19 18 27 24 27 11 23 19 24 27 12 25 12 15 11 13 23 + 29 19 19 13 27 18 12 14 27 14 28 15 23 20 13 18 25 + 12 13 19 23 23 24 28 16 16 19 28 25 16 19 26 23 27 + 0 28 28 28 26 19 25 0 28 11 24 27 24 16 28 28 19 + 26 19 14 19 23 18 25 18 28 26 25 16 19 27 19 12 25 + 19 27 28 27 12 25 27 25 28 4 23 27 28 23 24 14 11 + + 15 4 10 24 23 24 18 11 22 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 18 24 24 23 24 12 12 12 24 + 24 24 19 24 24 21 24 24 24 24 24 11 21 24 15 21 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 13 18 24 + 24 24 13 10 24 24 22 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 5 24 24 9 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 0 16 20 20 18 15 24 15 23 7 + 20 14 12 12 12 15 18 24 14 23 24 24 23 14 24 24 4 + 10 10 15 23 23 12 14 14 24 21 23 14 14 14 20 16 23 + 1 21 14 24 20 23 14 23 23 18 23 24 12 20 18 21 23 + 11 23 23 12 23 9 13 24 24 12 10 14 10 23 24 15 11 + 21 1 11 23 23 24 15 12 21 1 18 11 12 20 24 12 18 + 11 18 23 15 23 15 14 23 15 23 13 20 14 11 15 12 13 + 24 12 12 12 23 15 14 23 23 23 24 11 18 10 23 13 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 18 23 + 18 24 24 24 23 16 21 18 24 18 18 23 18 10 24 24 15 + 23 12 18 23 12 7 21 5 24 23 20 10 12 23 15 13 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 0 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 0 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 20 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 0 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 0 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 0 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 0 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 0 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 0 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 0 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 0 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 0 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 0 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 18 30 12 30 25 18 20 23 26 24 23 23 15 25 15 + 29 24 24 28 23 27 29 10 20 30 30 28 30 23 15 14 30 + 30 30 20 30 30 20 30 30 30 28 30 16 26 30 15 20 26 + 23 14 24 25 15 29 27 26 30 30 25 28 12 29 14 10 28 + 30 30 23 18 30 30 20 24 30 25 30 15 30 4 30 30 30 + 30 30 30 30 30 20 30 28 20 30 30 30 21 25 30 18 24 + 25 29 21 24 21 24 23 14 30 30 30 30 30 30 30 30 24 + 30 30 11 30 30 30 30 20 15 25 25 11 24 29 24 15 20 + 0 15 15 0 23 12 12 29 24 27 29 28 27 20 29 29 20 + 18 18 20 15 12 15 12 12 28 15 11 12 12 15 20 15 15 + 20 10 12 29 25 15 12 15 27 23 28 28 15 25 11 26 12 + 23 28 27 15 15 20 21 30 28 15 18 15 21 15 29 12 20 + 20 20 16 15 12 28 24 23 15 20 15 23 15 0 29 23 24 + 16 20 28 24 27 12 24 15 24 28 14 25 12 16 12 14 23 + 30 15 15 14 28 20 12 12 28 12 28 16 24 21 11 20 25 + 11 12 15 23 23 25 28 18 18 15 29 26 18 15 27 23 27 + 10 28 29 28 27 15 26 10 29 12 25 27 24 18 28 29 15 + 27 15 15 15 23 20 26 20 29 27 25 18 15 28 15 14 26 + 15 28 28 28 11 25 28 25 29 10 23 28 29 24 24 12 12 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 0 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 0 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 0 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 0 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 0 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 0 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 0 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 0 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 0 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 0 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 15 15 16 21 25 21 11 16 16 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 15 21 21 16 21 12 20 21 21 + 21 21 15 21 21 15 21 21 21 18 21 18 12 21 23 15 12 + 11 21 10 11 25 20 14 12 21 21 11 18 26 20 21 24 18 + 21 21 12 16 21 21 16 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 1 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 1 20 0 25 15 + 24 23 21 20 12 23 23 20 10 14 20 18 14 15 0 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 15 23 25 + 15 24 23 20 12 25 23 25 15 12 16 18 20 12 23 12 25 + 12 16 15 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 15 15 18 25 25 18 0 11 24 15 24 12 21 24 20 11 11 + 18 15 16 2 15 23 10 25 6 16 21 12 23 18 23 21 11 + 21 21 20 21 16 15 23 26 16 26 18 18 11 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 11 15 + 24 18 20 18 14 23 12 24 20 23 11 15 11 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 16 18 16 25 12 16 12 20 24 12 16 20 10 10 26 23 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 0 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 14 2 10 24 23 24 18 10 21 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 16 24 24 23 24 12 12 12 24 + 24 24 18 24 24 20 24 24 24 24 24 11 21 24 15 20 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 21 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 7 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 6 + 20 14 12 12 12 15 16 24 14 23 24 24 23 13 24 24 0 + 10 10 14 23 23 12 14 14 24 21 23 14 14 14 19 16 23 + 3 21 14 24 20 23 14 23 23 16 23 24 12 20 16 21 23 + 11 23 23 12 23 7 12 24 24 12 10 14 10 23 24 15 9 + 20 3 11 23 23 24 15 12 21 3 18 11 12 20 24 12 16 + 11 16 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 14 14 23 23 23 24 11 16 10 23 12 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 16 23 + 18 24 24 24 23 16 21 18 24 16 18 23 16 10 24 24 15 + 23 12 16 23 12 6 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 0 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 0 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 0 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 23 23 23 31 0 31 27 23 23 24 28 26 24 24 16 27 15 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 15 31 28 28 31 31 27 31 10 31 18 12 31 + 31 31 24 23 31 31 23 26 31 27 31 15 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 15 27 27 14 25 31 25 15 23 + 12 16 18 20 24 15 15 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 15 10 16 16 16 23 15 15 + 23 11 16 31 27 15 16 15 29 24 30 31 20 27 14 28 4 + 24 30 29 20 15 23 23 31 31 18 23 16 23 15 31 15 23 + 23 23 21 15 0 31 25 24 15 23 15 24 18 12 31 24 26 + 21 23 30 25 29 15 25 15 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 10 9 15 24 24 27 31 23 23 15 31 28 23 15 28 24 29 + 12 31 31 31 28 15 28 12 31 15 27 29 25 23 31 31 15 + 28 18 20 15 24 23 28 23 31 28 27 23 18 30 15 18 28 + 15 30 31 30 10 27 30 27 31 12 24 30 31 25 26 10 15 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 0 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 0 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 0 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 0 26 14 15 9 7 3 19 11 16 + 14 14 2 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 0 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 21 31 10 31 26 21 23 24 27 25 24 24 15 27 15 + 31 24 24 30 24 28 31 12 23 31 31 29 31 24 18 16 31 + 31 31 23 31 31 23 31 31 31 30 31 20 27 31 15 23 27 + 24 16 24 26 15 31 28 27 31 31 26 30 11 31 16 12 30 + 31 31 24 21 31 31 23 25 31 26 31 15 31 11 31 31 31 + 31 31 31 31 31 23 31 30 23 31 31 31 23 26 31 21 25 + 27 31 23 24 23 24 23 16 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 23 15 27 27 12 25 31 25 15 23 + 11 15 16 18 24 14 14 31 24 28 31 30 28 23 31 31 23 + 21 21 23 15 11 16 15 15 30 0 0 15 15 15 23 15 15 + 23 10 15 31 27 15 15 15 28 23 29 30 18 27 12 27 10 + 23 29 28 18 15 23 23 31 30 16 21 15 23 15 31 14 23 + 23 23 20 15 10 30 25 24 15 23 15 23 16 11 31 24 25 + 20 23 29 25 28 14 24 15 25 29 16 27 15 20 14 16 24 + 31 16 18 16 29 23 15 11 29 11 30 20 24 23 9 23 27 + 0 10 15 24 24 26 30 21 21 15 31 27 21 15 28 24 28 + 12 30 31 30 28 15 27 12 31 14 26 28 25 21 30 31 15 + 28 16 18 15 24 23 27 23 31 28 27 21 16 29 15 16 27 + 15 29 30 29 0 27 29 27 31 12 24 29 31 24 25 11 14 + + 21 21 20 31 15 31 25 20 24 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 23 31 31 31 29 31 18 27 31 12 23 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 15 29 + 31 31 23 20 31 31 24 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 19 24 30 24 11 21 + 15 14 15 16 23 15 19 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 0 0 14 14 14 22 12 11 + 21 5 14 30 26 11 14 11 28 23 28 29 16 26 19 27 19 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 23 21 18 11 15 29 24 24 0 21 11 23 15 15 30 24 25 + 18 21 28 24 28 15 24 11 24 28 15 26 14 18 15 15 24 + 31 15 16 15 28 21 15 12 28 12 29 18 24 23 10 21 26 + 15 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 19 29 30 29 27 12 27 19 30 19 25 28 24 20 29 30 12 + 27 15 19 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 15 26 28 26 30 15 23 28 30 24 25 15 12 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 7 26 14 15 0 7 3 19 11 16 + 14 14 2 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 0 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 0 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 0 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 0 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 0 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 0 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 20 31 13 31 25 20 22 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 21 31 31 31 29 31 18 27 31 12 21 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 13 29 + 31 31 23 20 31 31 22 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 18 24 30 24 11 21 + 13 14 15 16 23 13 18 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 1 13 14 14 14 21 12 11 + 21 0 14 30 26 11 14 11 28 23 28 29 16 26 18 27 18 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 21 21 18 11 13 29 24 24 1 21 11 23 15 13 30 24 25 + 18 21 28 24 28 13 24 11 24 28 15 26 14 18 13 15 24 + 31 15 16 15 28 21 14 12 28 12 29 18 24 23 10 21 26 + 13 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 18 29 30 29 27 12 27 18 30 18 25 28 24 20 29 30 12 + 27 15 18 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 13 26 28 26 30 13 23 28 30 24 25 13 12 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 7 26 14 15 9 7 3 19 11 16 + 14 14 0 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 0 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 12 11 26 20 26 23 11 22 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 18 26 26 24 26 15 1 10 26 + 26 26 19 26 26 21 26 26 26 25 26 10 23 26 12 21 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 13 14 25 + 26 26 15 11 26 26 22 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 18 20 25 20 20 12 + 15 11 10 1 15 13 18 25 18 24 25 25 24 14 25 25 12 + 11 11 15 20 21 10 11 11 25 16 18 11 11 11 20 12 20 + 12 16 11 25 0 20 11 20 24 18 24 25 8 23 18 23 20 + 14 24 24 1 20 12 13 26 25 10 11 11 12 20 25 12 12 + 21 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 18 24 20 24 13 18 20 20 24 13 23 11 10 13 10 16 + 26 10 1 10 24 15 13 21 24 21 25 10 18 12 18 13 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 18 24 + 18 25 25 25 24 12 23 18 25 18 23 24 20 11 25 25 12 + 24 10 18 20 15 12 23 12 25 24 23 11 10 24 12 13 23 + 20 24 25 24 18 23 24 23 25 14 15 24 25 18 21 21 12 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 0 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 0 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 0 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 14 28 14 12 23 24 18 11 12 18 18 24 11 26 + 12 15 15 12 16 10 15 26 23 14 14 11 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 12 14 23 10 14 25 23 10 + 16 24 15 12 28 12 19 10 14 14 12 12 29 15 24 26 12 + 14 14 18 23 14 14 24 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 12 23 14 14 14 21 12 14 23 14 + 11 12 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 12 14 28 23 + 27 24 24 24 18 25 25 12 15 0 12 12 15 23 12 12 23 + 23 23 23 28 29 24 24 24 12 27 28 24 24 24 23 25 28 + 23 27 24 12 12 28 24 28 0 20 11 19 24 11 25 10 28 + 20 15 19 24 28 23 21 19 12 24 23 24 21 28 12 25 23 + 23 23 23 28 28 12 14 16 27 23 26 20 24 27 12 16 19 + 23 23 11 14 10 25 15 28 14 19 24 11 24 23 25 24 16 + 19 24 24 24 11 23 24 29 15 29 19 23 19 21 28 23 11 + 28 28 25 16 18 12 12 23 23 25 12 10 23 28 10 19 15 + 26 12 12 12 15 25 15 26 12 25 12 10 19 23 12 15 25 + 6 24 24 28 18 23 10 23 12 15 11 23 24 11 25 24 10 + 28 19 15 11 28 11 11 11 12 26 18 19 12 15 12 29 25 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 0 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 0 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 0 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 0 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 0 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 0 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 0 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 0 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 0 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 0 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 0 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 0 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 0 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 4 10 24 23 24 18 11 22 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 18 24 24 23 24 12 12 12 24 + 24 24 19 24 24 21 24 24 24 24 24 11 21 24 15 21 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 13 18 24 + 24 24 13 10 24 24 22 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 5 24 24 9 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 4 16 20 20 18 15 24 15 23 7 + 20 14 12 12 12 15 18 24 14 23 24 24 23 14 24 24 4 + 10 10 15 23 23 12 14 14 24 21 23 14 14 14 20 16 23 + 1 21 14 24 20 23 14 23 23 18 23 24 12 20 18 21 23 + 11 23 23 12 23 0 13 24 24 12 10 14 10 23 24 15 11 + 21 1 11 23 23 24 15 12 21 1 18 11 12 20 24 12 18 + 11 18 23 15 23 15 14 23 15 23 13 20 14 11 15 12 13 + 24 12 12 12 23 15 14 23 23 23 24 11 18 10 23 13 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 18 23 + 18 24 24 24 23 16 21 18 24 18 18 23 18 10 24 24 15 + 23 12 18 23 12 7 21 5 24 23 20 10 12 23 15 13 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 0 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 0 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 0 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 0 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 0 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 0 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 0 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 0 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 0 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 0 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 14 14 15 23 25 23 12 15 21 11 14 11 11 11 21 12 23 + 21 3 8 20 10 16 21 23 16 23 23 18 23 11 18 20 23 + 23 23 18 23 23 20 23 23 23 20 23 16 14 23 23 20 14 + 10 20 5 12 25 21 16 14 23 23 12 20 25 21 20 23 20 + 23 23 12 15 23 23 21 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 5 12 2 12 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 11 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 19 23 25 + 14 24 21 21 12 25 21 25 16 16 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 0 + 20 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 16 + 16 16 18 10 16 23 8 25 11 18 20 12 21 16 23 20 12 + 23 20 18 20 18 14 21 25 18 25 20 16 16 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 16 16 + 23 20 21 20 15 23 14 23 21 23 12 16 16 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 3 11 25 23 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 0 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 0 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 0 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 0 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 0 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 12 12 14 23 24 23 12 14 12 10 15 15 10 10 20 15 23 + 23 10 10 21 4 18 23 23 12 23 23 20 23 10 16 18 23 + 23 23 12 23 23 12 23 23 23 21 23 15 15 23 21 12 15 + 9 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 12 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 15 12 23 14 11 + 14 23 12 10 12 10 15 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 12 23 24 + 15 24 20 23 14 24 20 24 18 11 20 21 16 15 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 15 24 23 21 12 + 12 15 15 24 24 0 11 8 24 15 23 15 18 23 23 15 12 + 15 12 20 11 18 21 10 24 11 20 18 14 20 15 21 18 0 + 23 18 16 18 20 12 20 25 20 25 21 15 10 12 24 12 14 + 24 24 21 15 10 12 21 14 14 23 23 15 14 24 16 4 18 + 23 21 23 21 16 23 15 23 23 21 12 18 11 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 15 20 23 15 15 25 21 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 0 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 14 14 15 23 25 23 12 15 21 11 14 11 11 11 21 12 23 + 21 3 8 20 10 16 21 23 16 23 23 18 23 11 18 20 23 + 23 23 18 23 23 20 23 23 23 20 23 16 14 23 23 20 14 + 10 20 5 12 25 21 16 14 23 23 12 20 25 21 20 23 20 + 23 23 12 15 23 23 21 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 5 12 2 12 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 11 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 19 23 25 + 14 24 21 21 12 25 21 25 16 16 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 20 14 16 25 25 20 10 0 24 14 23 12 20 24 21 10 16 + 16 16 18 10 16 23 8 25 11 18 20 12 21 16 23 20 12 + 23 20 18 20 18 14 21 25 18 25 20 16 16 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 16 16 + 23 20 21 20 15 23 14 23 21 23 12 16 16 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 3 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 0 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 0 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 0 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 0 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 0 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 0 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 0 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 0 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 0 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 0 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 0 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 0 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 0 15 23 11 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 11 10 11 24 23 24 16 11 18 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 13 24 24 23 24 11 12 14 24 + 24 24 15 24 24 17 24 24 24 23 24 12 20 24 16 17 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 18 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 6 16 24 11 14 + 18 24 4 12 4 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 11 23 24 14 15 15 23 23 23 15 15 15 16 18 23 + 10 23 15 24 18 23 15 23 23 13 23 23 12 18 18 20 23 + 10 23 23 12 23 10 9 24 23 14 11 15 6 23 24 16 10 + 17 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 13 23 14 0 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 11 15 24 23 24 23 12 13 0 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 13 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 13 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 23 23 23 12 29 12 12 23 24 20 11 14 20 20 25 12 27 + 12 16 16 11 18 10 15 27 23 12 12 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 19 11 12 12 12 11 30 15 24 27 11 + 12 12 20 23 12 12 24 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 15 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 15 21 10 19 24 12 26 11 29 + 21 15 19 24 29 23 23 19 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 19 + 24 23 10 15 0 0 16 29 15 19 24 12 25 24 25 24 18 + 19 24 24 24 10 23 25 30 15 30 19 24 19 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 19 15 + 27 11 12 11 15 26 15 27 12 25 12 0 19 23 11 15 25 + 10 24 24 29 20 23 11 23 12 15 12 23 24 10 25 24 11 + 29 19 15 10 28 12 10 12 12 27 20 19 12 16 14 30 25 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 5 15 23 0 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 0 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 0 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 0 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 0 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 0 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 0 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 0 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 0 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 17 10 11 24 23 24 16 12 24 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 19 24 24 23 24 11 12 14 24 + 24 24 21 24 24 23 24 24 24 23 24 12 20 24 16 23 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 15 20 23 + 24 24 15 11 24 24 24 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 0 16 24 11 14 + 18 24 10 12 10 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 19 14 24 14 23 10 + 21 15 14 12 11 16 19 24 14 21 24 23 21 16 24 24 10 + 11 11 17 23 24 14 15 15 23 23 23 15 15 15 22 18 23 + 10 23 15 24 18 23 15 23 23 19 23 23 12 18 19 20 23 + 10 23 23 12 23 10 15 24 23 14 11 15 0 23 24 16 12 + 23 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 19 + 12 19 23 14 23 16 12 23 14 23 15 18 15 12 16 0 15 + 24 14 12 14 23 17 15 24 23 24 23 12 19 6 23 15 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 19 23 + 20 23 24 23 21 18 20 20 24 19 16 23 19 11 23 24 16 + 21 14 19 23 14 10 20 10 24 21 18 11 14 23 16 15 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 0 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 0 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 0 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 14 11 26 20 26 23 11 12 15 23 21 15 15 19 23 19 + 25 18 18 25 16 24 25 14 12 26 26 24 26 15 19 13 26 + 26 26 12 26 26 12 26 26 26 25 26 19 23 26 19 12 23 + 16 13 18 23 20 25 24 23 26 26 23 25 21 25 10 14 25 + 26 26 15 11 26 26 12 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 19 23 26 11 20 + 23 25 12 18 12 18 19 13 26 26 26 26 26 26 26 26 18 + 26 26 13 26 26 26 26 14 19 23 23 12 20 25 20 20 12 + 15 19 19 19 15 12 12 25 18 24 25 25 24 12 25 25 14 + 14 11 12 20 21 19 11 11 25 19 18 11 11 19 12 19 20 + 19 16 14 25 23 20 11 20 24 14 24 25 9 23 12 23 20 + 14 24 24 19 20 12 12 26 25 19 11 19 19 20 25 14 12 + 12 19 19 20 20 25 20 16 19 19 19 19 19 15 25 19 21 + 19 12 24 20 24 12 18 20 20 24 10 23 11 13 12 13 16 + 26 19 0 13 24 12 11 21 24 21 25 10 18 13 18 12 23 + 18 20 19 19 15 23 25 11 12 19 25 23 14 20 24 16 24 + 14 25 25 25 24 19 23 14 25 12 23 24 20 11 25 25 19 + 24 19 0 20 15 12 23 12 25 24 23 11 19 24 19 10 23 + 20 24 25 24 18 23 24 23 25 14 19 24 25 19 21 21 12 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 0 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 0 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 0 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 0 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 15 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 0 24 23 24 10 19 12 20 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 21 21 20 31 15 31 25 20 24 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 23 31 31 31 29 31 18 27 31 12 23 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 15 29 + 31 31 23 20 31 31 24 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 19 24 30 24 11 21 + 15 14 15 16 23 15 19 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 0 15 14 14 14 22 12 11 + 21 5 14 30 26 11 14 11 28 23 28 29 16 26 19 27 19 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 23 21 18 11 15 29 24 24 0 21 11 23 15 15 30 24 25 + 18 21 28 24 28 15 24 11 24 28 15 26 14 18 15 15 24 + 31 15 16 15 28 21 15 12 0 12 29 18 24 23 10 21 26 + 15 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 19 29 30 29 27 12 27 19 30 19 25 28 24 20 29 30 12 + 27 15 19 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 15 26 28 26 30 15 23 28 30 24 25 15 12 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 0 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 18 18 16 29 15 29 24 16 24 23 25 24 23 23 12 25 0 + 28 23 23 28 23 27 28 10 19 29 29 27 29 23 14 12 29 + 29 29 21 29 29 23 29 29 29 28 29 15 25 29 11 23 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 15 15 28 + 29 29 23 16 29 29 24 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 29 29 29 18 10 25 25 19 24 28 24 12 18 + 15 12 12 14 23 15 19 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 15 12 12 12 22 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 19 25 19 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 23 18 15 12 15 28 24 23 11 18 0 21 12 15 28 23 24 + 15 19 27 24 27 15 23 12 24 27 15 25 12 15 15 12 23 + 29 12 14 12 27 18 15 14 27 14 0 15 23 20 12 18 25 + 15 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 19 28 28 28 26 10 25 19 28 19 24 27 24 16 28 28 11 + 26 12 19 12 23 18 25 18 28 26 25 16 12 27 11 15 25 + 12 27 28 27 15 25 27 25 28 15 23 27 28 23 24 15 11 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 0 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 0 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 17 12 14 23 24 23 12 14 24 10 15 12 10 10 20 14 23 + 23 10 11 21 10 18 23 23 19 23 23 20 23 10 16 18 23 + 23 23 21 23 23 23 23 23 23 21 23 15 15 23 21 23 15 + 5 18 10 12 24 23 19 15 23 23 12 21 25 23 18 23 21 + 23 23 15 14 23 23 24 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 14 16 23 21 16 16 23 23 12 + 14 14 17 24 25 18 20 20 21 24 24 20 20 20 22 23 24 + 12 24 20 23 14 24 20 24 18 19 20 21 16 14 23 15 24 + 11 20 19 16 24 12 15 23 21 18 14 20 12 24 23 21 12 + 23 12 15 24 24 21 11 6 24 12 23 11 18 23 23 0 19 + 15 19 20 11 18 21 11 24 14 20 18 14 20 15 21 18 15 + 23 18 16 18 20 17 20 25 20 25 21 15 19 0 24 15 14 + 24 24 21 0 10 12 21 14 14 23 23 15 14 24 16 19 18 + 23 21 23 21 16 23 15 23 23 21 12 18 19 14 21 23 21 + 16 18 19 24 14 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 15 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 23 24 23 24 10 19 12 0 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 0 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 0 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 0 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 0 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 0 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 0 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 0 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 0 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 0 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 0 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 0 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 0 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 0 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 0 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 0 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 0 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 0 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 17 12 14 23 24 23 12 14 24 10 15 12 10 10 20 14 23 + 23 10 11 21 10 18 23 23 19 23 23 20 23 10 16 18 23 + 23 23 21 23 23 23 23 23 23 21 23 15 15 23 21 23 15 + 5 18 10 12 24 23 19 15 23 23 12 21 25 23 18 23 21 + 23 23 15 14 23 23 24 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 14 16 23 21 16 16 23 23 12 + 14 14 17 24 25 18 20 20 21 24 24 20 20 20 22 23 24 + 12 24 20 23 14 24 20 24 18 19 20 21 16 14 23 15 24 + 11 20 19 16 24 12 15 23 21 18 14 20 12 24 23 21 12 + 23 12 15 24 24 21 11 6 24 12 23 11 18 23 23 0 19 + 15 19 20 11 18 21 11 24 14 20 18 14 20 15 21 18 15 + 23 18 16 18 20 17 20 25 20 25 21 15 19 12 24 15 14 + 24 24 21 0 10 12 21 14 14 23 23 15 14 24 16 0 18 + 23 21 23 21 16 23 15 23 23 21 12 18 19 14 21 23 21 + 16 18 19 24 14 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 0 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 0 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 0 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 0 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 6 21 21 10 23 12 9 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 6 13 14 10 10 16 10 31 9 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 6 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 6 20 31 24 + 29 27 26 25 23 27 27 6 21 12 6 10 12 24 6 0 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 6 15 31 27 31 12 23 11 13 25 15 28 14 31 + 23 11 13 25 31 24 24 13 10 26 24 27 24 31 6 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 6 23 18 + 25 24 11 20 12 27 21 31 20 13 26 15 27 25 27 26 23 + 13 26 25 26 11 24 27 31 11 31 13 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 6 14 24 31 12 23 12 + 28 10 0 0 12 28 14 28 6 27 16 12 20 24 10 9 27 + 12 26 25 31 23 24 14 24 6 12 15 24 26 11 27 26 14 + 31 13 10 11 31 15 11 15 6 28 23 13 6 21 18 31 27 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 0 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 0 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 0 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 0 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 14 14 15 23 25 23 12 15 14 14 14 19 12 12 21 19 23 + 21 12 8 20 10 16 21 23 14 23 23 19 23 11 19 20 23 + 23 23 14 23 23 14 23 23 23 20 23 19 19 23 23 14 14 + 14 20 11 12 25 21 15 14 23 23 14 20 25 21 20 23 20 + 23 23 11 15 23 23 14 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 19 12 23 15 12 + 12 21 12 11 12 14 19 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 14 12 23 12 21 11 25 14 + 24 21 20 19 11 23 23 21 5 19 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 19 24 21 21 12 25 21 25 16 12 18 20 18 19 23 14 25 + 12 18 16 19 25 14 12 23 20 20 15 21 19 25 21 23 14 + 14 19 19 25 25 20 11 12 24 19 23 19 20 24 21 19 11 + 19 14 19 14 19 23 8 25 10 18 20 13 21 16 23 20 10 + 23 20 19 20 19 14 21 25 18 25 20 16 0 13 24 14 12 + 24 25 23 19 14 12 20 15 15 23 21 14 15 25 15 10 16 + 23 20 21 20 15 23 14 23 0 23 12 19 10 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 19 + 25 18 20 19 24 12 19 13 21 23 19 18 21 19 19 25 23 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 0 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 0 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 0 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 12 29 12 12 23 24 20 11 14 20 20 25 12 27 + 12 16 16 11 18 10 15 27 23 12 12 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 19 11 12 12 12 11 30 15 24 27 11 + 12 12 20 23 12 12 24 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 15 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 15 21 10 19 24 12 26 11 29 + 21 15 19 24 29 23 23 19 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 19 + 24 23 10 15 0 25 16 29 15 19 24 12 25 24 25 24 18 + 19 24 24 24 10 23 25 30 15 30 19 24 19 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 19 15 + 27 11 12 11 15 26 15 27 12 25 12 0 0 23 11 15 25 + 10 24 24 29 20 23 11 23 12 15 12 23 24 10 25 24 11 + 29 19 15 10 28 12 10 12 12 27 20 19 12 16 14 30 25 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 0 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 23 23 23 14 28 14 12 23 23 18 10 15 18 18 24 15 26 + 15 15 15 15 16 10 12 26 23 14 14 15 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 23 15 14 25 23 10 + 16 24 15 12 28 15 4 10 14 14 12 15 29 12 24 26 12 + 14 14 18 23 14 14 23 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 21 12 14 23 14 + 11 15 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 15 14 28 23 + 27 24 24 24 18 25 25 15 15 15 15 15 0 23 15 12 23 + 23 23 23 28 29 24 24 24 15 27 28 24 24 24 23 25 28 + 23 27 24 15 11 28 24 28 10 20 11 12 24 15 25 10 28 + 20 11 10 24 28 23 21 14 15 24 23 24 21 28 15 25 23 + 23 23 23 28 28 15 14 16 27 23 26 20 24 27 15 16 12 + 23 23 15 14 15 25 15 28 14 11 24 11 24 23 25 24 16 + 14 24 24 24 15 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 16 18 12 15 23 23 25 15 10 23 28 4 16 10 + 26 12 12 15 0 25 10 26 15 25 12 15 14 23 0 12 25 + 9 24 24 28 18 23 10 23 15 0 11 23 24 11 25 24 15 + 28 11 12 15 28 11 15 11 15 26 18 11 15 15 15 29 25 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 0 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 0 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 0 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 0 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 0 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 0 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 0 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 0 10 20 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 20 20 21 16 27 16 10 21 22 15 10 11 15 15 24 1 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 21 16 16 16 14 16 23 10 16 24 21 10 + 14 23 12 10 27 15 18 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 22 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 5 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 4 7 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 13 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 11 27 24 27 13 18 12 18 23 1 24 10 27 + 16 13 18 23 27 20 18 18 14 23 21 24 18 27 15 24 20 + 21 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 18 + 23 20 12 12 12 24 12 27 12 18 23 4 24 23 24 23 14 + 18 23 23 23 12 20 24 28 13 28 18 23 18 18 27 20 8 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 18 13 + 25 14 15 14 13 24 13 25 15 24 10 12 18 21 14 15 24 + 11 23 23 27 15 20 0 20 15 13 7 21 23 12 24 23 10 + 27 18 14 12 27 6 12 4 15 25 15 18 15 12 11 28 24 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 0 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 0 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 0 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 20 15 12 0 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 18 18 20 18 27 18 9 20 24 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 19 18 18 14 18 14 23 23 18 + 18 18 21 18 18 23 18 18 18 15 18 21 11 18 24 23 11 + 12 23 12 6 27 16 19 11 18 18 5 15 27 16 23 24 15 + 18 18 15 20 18 18 24 10 18 11 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 9 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 14 12 16 15 15 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 22 24 27 + 18 25 23 16 12 27 23 27 15 19 14 19 23 10 24 11 27 + 15 15 19 23 27 18 16 19 15 23 20 23 16 27 16 24 18 + 23 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 19 + 21 19 14 11 12 24 12 27 14 19 23 10 23 21 24 23 15 + 19 23 23 23 14 18 23 27 15 27 19 21 19 16 26 18 10 + 26 27 24 12 14 10 15 20 20 24 16 11 20 27 12 19 15 + 24 15 16 15 15 24 15 24 16 24 9 12 19 20 15 16 24 + 12 23 23 27 14 18 11 18 16 15 10 0 23 14 24 23 11 + 27 19 15 14 26 10 14 10 16 24 14 19 16 12 10 27 24 + + 20 20 18 30 12 30 25 18 20 23 26 24 23 23 15 25 15 + 29 24 24 28 23 27 29 10 20 30 30 28 30 23 15 14 30 + 30 30 20 30 30 20 30 30 30 28 30 16 26 30 15 20 26 + 23 14 24 25 15 29 27 26 30 30 25 28 12 29 14 10 28 + 30 30 23 18 30 30 20 24 30 25 30 15 30 4 30 30 30 + 30 30 30 30 30 20 30 28 20 30 30 30 21 25 30 18 24 + 25 29 21 24 21 24 23 14 30 30 30 30 30 30 30 30 24 + 30 30 11 30 30 30 30 20 15 25 25 11 24 29 24 15 20 + 0 15 15 15 23 12 12 29 24 27 29 28 27 20 29 29 20 + 18 18 20 15 12 15 12 12 28 15 11 12 12 15 20 15 15 + 20 10 12 29 25 15 12 15 27 23 28 28 15 25 11 26 12 + 23 28 27 15 15 20 21 30 28 15 18 15 21 15 29 12 20 + 20 20 16 15 12 28 24 23 15 20 15 23 15 0 29 23 24 + 16 20 28 24 27 12 24 15 24 28 14 25 12 16 12 14 23 + 30 15 15 14 28 20 12 12 28 12 28 16 24 21 11 20 25 + 11 12 15 23 23 25 28 18 18 15 29 26 18 15 27 23 27 + 10 28 29 28 27 15 26 10 29 12 25 27 24 18 28 29 15 + 27 15 15 15 23 20 26 20 29 27 25 18 0 28 15 14 26 + 15 28 28 28 11 25 28 25 29 10 23 28 29 24 24 12 12 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 0 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 0 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 0 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 0 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 0 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 0 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 0 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 0 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 0 12 0 12 11 27 21 19 11 18 15 31 26 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 0 12 10 14 25 16 19 14 14 12 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 0 16 10 29 23 18 10 23 20 33 28 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 0 11 27 21 19 11 18 15 31 26 + + 24 24 24 14 31 14 15 24 24 23 12 16 23 23 26 15 28 + 15 20 20 15 21 11 10 28 24 14 14 15 14 23 25 25 14 + 14 14 24 14 14 24 14 14 14 15 14 24 15 14 27 24 12 + 21 25 20 15 31 15 12 12 14 14 15 15 31 10 25 28 9 + 14 14 23 24 14 14 24 16 14 15 14 31 14 28 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 23 15 14 24 18 + 14 15 23 20 23 20 23 25 14 14 14 14 14 14 14 14 20 + 14 14 27 14 14 14 14 24 27 14 14 27 18 15 18 31 24 + 28 26 25 25 23 27 27 15 20 15 15 15 12 24 15 10 24 + 24 24 24 31 31 25 26 26 15 29 30 26 26 26 24 27 31 + 24 29 26 15 14 31 26 31 11 23 10 4 25 15 27 12 31 + 23 10 11 25 31 24 23 11 15 25 24 26 23 31 15 27 24 + 24 24 24 31 31 15 18 21 29 24 28 23 25 28 15 21 16 + 24 24 15 18 15 27 20 31 18 10 25 14 26 24 27 25 21 + 11 25 25 25 15 24 26 31 10 31 4 24 20 23 30 24 14 + 30 31 27 21 23 15 15 24 24 27 15 12 24 31 12 21 11 + 28 4 10 15 12 27 12 28 15 27 15 15 18 24 15 10 27 + 12 25 25 31 23 24 12 24 15 12 14 24 25 10 27 25 15 + 31 10 0 15 30 14 15 14 0 28 23 10 15 20 16 31 27 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 0 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 0 18 10 23 20 33 28 + + 17 12 12 23 24 23 14 12 24 5 16 12 6 6 18 15 23 + 23 11 11 23 10 20 23 23 19 23 23 21 23 10 15 16 23 + 23 23 21 23 23 23 23 23 23 23 23 14 16 23 20 23 16 + 10 16 11 14 24 23 19 16 23 23 14 23 24 23 16 23 23 + 23 23 15 12 23 23 24 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 11 14 23 12 12 + 15 23 11 11 11 11 10 16 23 23 23 23 23 23 23 23 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 10 20 20 23 14 18 23 23 18 16 23 23 12 + 12 12 17 24 24 16 18 18 23 23 24 18 18 18 22 21 24 + 12 23 18 23 15 24 18 24 20 19 21 23 15 15 21 16 24 + 10 21 20 15 24 12 15 23 23 16 12 18 11 24 23 20 12 + 23 12 14 24 24 23 12 10 23 12 23 10 16 23 23 10 19 + 14 19 21 12 20 20 11 24 14 21 16 15 18 14 20 16 15 + 23 16 15 16 21 17 18 24 21 24 23 14 19 11 24 15 15 + 24 24 20 10 5 14 23 12 12 21 23 16 12 24 18 19 20 + 23 23 23 23 18 21 16 23 23 20 14 20 19 12 23 23 20 + 18 16 19 24 14 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 0 0 23 11 12 24 20 + + 23 23 23 14 28 14 12 23 23 18 10 15 18 18 24 15 26 + 15 15 15 15 16 10 12 26 23 14 14 15 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 23 15 14 25 23 10 + 16 24 15 12 28 15 4 10 14 14 12 15 29 12 24 26 12 + 14 14 18 23 14 14 23 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 21 12 14 23 14 + 11 15 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 15 14 28 23 + 27 24 24 24 18 25 25 15 15 15 15 15 0 23 15 12 23 + 23 23 23 28 29 24 24 24 15 27 28 24 24 24 23 25 28 + 23 27 24 15 11 28 24 28 10 20 11 12 24 15 25 10 28 + 20 11 10 24 28 23 21 14 15 24 23 24 21 28 15 25 23 + 23 23 23 28 28 15 14 16 27 23 26 20 24 27 15 16 12 + 23 23 15 14 15 25 15 28 14 11 24 11 24 23 25 24 16 + 14 24 24 24 15 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 16 18 12 15 23 23 25 15 10 23 28 4 16 10 + 26 12 12 15 0 25 10 26 15 25 12 15 14 23 15 12 25 + 9 24 24 28 18 23 10 23 15 0 11 23 24 11 25 24 15 + 28 11 12 15 28 11 15 11 15 26 18 11 0 15 15 29 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 0 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 0 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 0 23 + + 17 16 18 20 26 20 10 18 24 12 12 0 12 12 23 11 24 + 18 11 11 16 12 14 18 24 19 20 20 15 20 12 21 23 20 + 20 20 21 20 20 23 20 20 20 16 20 20 12 20 23 23 12 + 12 23 11 10 26 18 19 12 20 20 10 16 27 18 23 24 16 + 20 20 15 18 20 20 24 8 20 11 20 26 20 24 20 20 20 + 20 20 20 20 20 16 20 16 16 20 20 20 15 10 20 18 10 + 11 18 15 11 15 11 14 23 20 20 20 20 20 20 20 20 11 + 20 20 24 20 20 20 20 16 24 11 11 24 10 18 10 26 16 + 24 23 23 21 12 23 23 18 14 12 18 16 15 16 18 18 16 + 18 18 17 26 27 23 23 23 16 25 25 23 23 23 22 24 26 + 16 25 23 18 12 26 23 26 15 19 15 19 21 11 24 12 26 + 14 15 19 21 26 16 15 20 16 23 18 23 15 26 18 23 16 + 23 16 20 26 26 16 10 12 25 16 24 14 23 24 18 12 19 + 20 19 15 10 14 23 11 26 14 19 23 11 23 20 23 23 15 + 20 23 21 23 15 17 23 27 15 27 19 20 19 15 25 16 11 + 25 26 23 12 12 10 16 18 18 24 18 12 18 26 12 19 15 + 24 16 18 16 15 24 15 24 18 23 10 14 19 18 16 18 23 + 12 23 21 26 14 16 12 16 18 15 11 18 23 15 23 23 12 + 26 19 16 15 25 11 15 11 18 24 12 19 18 11 0 27 0 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ry48p.atsp b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ry48p.atsp new file mode 100644 index 0000000..b02a98c --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ATSP-instances/ry48p.atsp @@ -0,0 +1,200 @@ +NAME: ry48p +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 48 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 1593 569 2056 1327 1009 947 301 234 1800 625 700 754 790 529 + 395 1385 856 1179 821 1085 385 730 1808 915 2076 1120 1002 1297 1026 + 592 1448 694 743 2254 880 1137 330 1121 449 786 1594 1264 755 2354 + 593 849 1216 + 1619 9999999 1191 656 595 2304 2128 1797 1674 834 1348 1620 1183 1050 1629 + 1339 2444 2039 2350 1646 1334 1322 1167 1079 1182 624 2307 2171 478 2272 + 1923 1192 1837 982 1060 2132 2312 1884 1047 1513 1051 550 2287 2125 1123 + 1765 1388 718 + 528 1297 9999999 1682 809 1309 1170 624 506 1445 526 488 561 402 610 + 429 1510 1072 1419 882 801 250 401 1351 485 1579 1436 1194 898 1194 + 816 1054 728 471 1828 1000 1276 837 898 465 459 1183 1314 989 1876 + 708 620 968 + 2097 723 1781 9999999 996 2674 2595 2360 2236 501 1846 2061 1616 1580 2108 + 1884 2678 2590 2635 2068 1584 1847 1638 930 1328 187 2635 2582 948 2669 + 2421 1197 2183 1506 620 2438 2782 2337 1328 1959 1513 680 2603 2497 648 + 2142 1827 1058 + 1310 680 780 1023 9999999 1690 1754 1424 1279 787 900 1153 759 612 1201 + 1098 1918 1682 1858 1148 876 975 761 759 639 820 1759 1651 417 1694 + 1459 718 1292 566 1005 1632 1870 1540 493 1131 954 496 1760 1629 1144 + 1306 886 295 + 1156 2218 1336 2687 1745 9999999 358 1020 964 2253 998 774 1089 1369 692 + 1349 364 339 249 801 1187 1286 1135 2157 1442 2473 276 303 1881 258 + 681 1588 708 1488 2624 391 254 704 1508 879 1636 2165 300 429 2588 + 668 1014 1735 + 827 2103 1085 2504 1692 258 9999999 972 759 2236 834 724 970 1102 604 + 1227 535 54 493 551 1165 1066 974 1908 1239 2379 508 124 1677 311 + 386 1483 590 1382 2444 204 391 614 1437 820 1410 2049 471 245 2595 + 386 858 1615 + 190 1684 698 2274 1395 1116 792 9999999 387 2016 797 691 984 1055 677 + 445 1348 868 1148 936 1246 404 816 1965 1191 2206 1272 1050 1323 1057 + 505 1607 839 890 2379 972 1098 327 1471 545 973 1756 1200 786 2415 + 616 920 1552 + 217 1673 526 2144 1366 1009 796 413 9999999 1941 696 570 899 793 452 + 515 1094 619 1003 758 937 524 615 1760 1020 2103 1133 749 1323 900 + 465 1379 477 762 2222 632 1020 317 1178 247 908 1609 1140 473 2205 + 392 824 1237 + 1892 856 1591 636 780 2323 2205 2133 2014 9999999 1544 1649 1258 1170 1709 + 1716 2377 2141 2443 1629 1320 1686 1395 378 1015 383 2367 2191 833 2283 + 2062 800 1897 1257 448 2138 2287 2109 803 1810 1520 415 2270 2119 478 + 1932 1486 706 + 660 1316 535 1817 893 1084 780 764 592 1407 9999999 323 304 464 344 + 787 1129 839 1180 507 450 669 189 1400 416 1760 992 905 963 975 + 745 890 503 643 1901 829 1118 775 749 403 986 1343 1039 813 1921 + 564 418 853 + 673 1626 580 1892 1168 829 719 745 438 1582 366 9999999 537 648 217 + 787 1031 541 896 370 568 609 434 1536 589 1928 807 792 1282 790 + 677 930 214 705 1993 690 926 561 936 442 987 1422 772 547 1895 + 410 343 1015 + 786 1289 570 1603 682 1203 1059 956 885 1353 297 547 9999999 328 632 + 937 1377 1023 1316 495 332 849 227 1130 254 1474 1322 1106 933 1097 + 955 530 617 535 1634 949 1254 884 521 702 891 1051 1127 1096 1568 + 844 326 758 + 776 1066 499 1584 536 1245 1106 1016 913 1157 331 690 236 9999999 746 + 720 1414 1137 1420 747 457 711 234 1016 211 1370 1479 1144 617 1341 + 1115 761 697 443 1549 1172 1452 939 461 555 768 949 1319 1135 1589 + 791 555 566 + 434 1750 629 2111 1152 812 635 592 499 1693 299 220 686 769 9999999 + 837 1005 609 839 473 664 664 440 1510 773 2009 952 567 1243 788 + 531 1137 228 918 2134 466 902 500 1012 333 916 1638 889 435 2012 + 373 519 1160 + 430 1369 449 1956 1178 1364 1169 534 490 1736 747 829 850 721 832 + 9999999 1524 1019 1405 1055 1018 221 649 1586 854 1849 1420 1180 1082 1460 + 920 1405 886 659 2137 1144 1366 685 1164 621 512 1489 1507 1040 2047 + 848 988 1247 + 1295 2527 1426 2755 1976 340 497 1247 1189 2385 1187 918 1228 1425 1065 + 1531 9999999 659 233 866 1323 1565 1347 2089 1544 2637 126 545 2079 346 + 772 1567 751 1683 2693 613 274 1026 1535 1207 1826 2313 171 795 2715 + 822 1033 1946 + 851 2101 1064 2399 1615 452 196 834 668 2196 775 586 1078 1175 512 + 1028 645 9999999 513 509 1136 909 1009 1929 1194 2379 419 165 1787 323 + 377 1412 467 1184 2407 118 370 608 1422 609 1362 2042 507 269 2516 + 311 838 1685 + 1210 2372 1385 2679 1919 125 516 1170 1001 2442 1102 873 1280 1418 955 + 1398 269 524 9999999 759 1146 1399 1311 2170 1428 2617 79 287 2039 310 + 680 1564 664 1553 2738 407 99 894 1569 1003 1787 2101 329 655 2629 + 808 934 1871 + 723 1779 819 2056 1170 726 592 967 815 1664 406 377 543 649 370 + 1104 750 631 866 9999999 499 841 652 1371 782 1895 694 658 1243 682 + 724 937 213 1047 2019 544 735 791 814 500 1189 1511 799 550 1948 + 438 262 1047 + 1005 1475 840 1600 715 1188 1122 1256 970 1208 508 618 304 615 716 + 999 1175 1107 1206 542 9999999 984 461 1106 460 1480 1125 1128 1115 1054 + 1132 571 755 708 1546 1033 1198 987 545 798 1228 1161 1075 1037 1506 + 876 346 791 + 404 1421 317 1918 1059 1275 1025 420 534 1663 616 660 745 742 683 + 328 1491 904 1452 882 921 9999999 559 1624 718 1903 1280 1053 978 1282 + 710 1140 809 557 2124 984 1278 702 1022 491 558 1414 1335 949 2111 + 695 791 1189 + 546 1189 345 1638 718 1246 1034 781 682 1314 251 504 225 264 593 + 685 1412 863 1312 570 521 614 9999999 1221 414 1559 1246 970 860 1134 + 868 724 662 436 1807 986 1162 706 620 469 665 1181 1090 930 1741 + 586 412 770 + 1695 962 1414 866 621 1982 1923 1990 1749 352 1256 1480 1015 1106 1502 + 1646 2199 1954 2105 1419 1063 1542 1227 9999999 875 798 2153 1991 950 1929 + 1892 683 1620 1115 725 1886 2083 1857 766 1520 1554 459 2052 2040 646 + 1834 1330 537 + 952 1029 537 1441 451 1411 1250 1051 833 1110 524 581 184 228 691 + 923 1568 1237 1419 765 423 873 429 1023 9999999 1310 1350 1283 719 1235 + 1158 538 901 518 1452 1060 1373 1166 461 645 851 966 1332 1218 1365 + 945 553 568 + 2061 722 1713 298 813 2633 2414 2254 2162 487 1606 1867 1419 1350 1900 + 1728 2730 2455 2548 1965 1542 1732 1654 755 1299 9999999 2571 2564 831 2422 + 2357 1210 2057 1254 464 2359 2669 2163 1071 1856 1577 497 2540 2371 714 + 2232 1643 952 + 1173 2364 1322 2759 1912 246 530 1243 1011 2335 1125 907 1166 1454 860 + 1547 298 463 75 661 1197 1362 1227 2108 1302 2550 9999999 381 2018 248 + 661 1602 780 1547 2606 420 191 880 1573 1000 1781 2079 174 619 2648 + 753 963 1735 + 872 2158 1106 2574 1739 273 278 943 833 2234 799 677 1120 1245 559 + 1161 484 163 337 574 1169 1163 970 2001 1196 2375 300 9999999 1849 265 + 508 1383 470 1421 2587 298 224 586 1380 880 1471 2064 358 421 2425 + 553 898 1601 + 1284 503 875 979 375 1874 1736 1429 1243 911 1052 1170 836 658 1334 + 1037 1998 1731 2002 1427 1041 1120 857 969 674 971 1966 1800 9999999 1785 + 1630 936 1323 562 1243 1670 2000 1464 791 1188 747 482 2009 1704 1232 + 1380 1060 565 + 1099 2354 1305 2528 1734 138 418 1078 934 2189 1030 752 1046 1218 717 + 1360 411 417 261 556 1122 1145 1085 1986 1225 2534 255 247 1956 9999999 + 596 1445 581 1540 2501 244 146 896 1491 946 1677 2102 263 483 2439 + 674 965 1749 + 672 1921 948 2388 1537 594 394 495 425 2053 849 589 973 1137 388 + 847 886 350 613 693 1076 778 791 1943 1066 2367 690 390 1561 612 + 9999999 1467 530 1124 2558 369 690 287 1441 455 1363 1989 709 283 2489 + 373 800 1504 + 1387 1277 1020 1219 545 1467 1455 1553 1281 883 765 950 675 770 1139 + 1245 1543 1437 1541 853 570 1325 824 534 657 1287 1625 1490 863 1468 + 1542 9999999 1015 891 1183 1448 1554 1406 266 1142 1162 765 1435 1465 1175 + 1278 700 632 + 747 1668 719 2159 1183 633 500 722 525 1896 400 251 636 742 322 + 812 931 385 692 236 727 855 678 1643 847 1988 774 490 1324 685 + 411 1093 9999999 1028 2141 469 655 532 1049 427 1228 1649 725 424 2064 + 190 462 1251 + 702 1023 383 1383 644 1420 1272 914 824 1280 575 723 604 352 820 + 695 1665 1366 1642 867 806 648 542 1173 567 1316 1504 1408 601 1556 + 1093 826 937 9999999 1521 1187 1466 964 764 617 399 1000 1492 1147 1647 + 980 701 554 + 2318 1080 1876 516 1131 2587 2633 2328 2298 516 1836 2047 1595 1561 2094 + 2137 2690 2509 2644 1942 1545 1967 1716 700 1385 594 2612 2552 1137 2467 + 2474 1260 2162 1513 9999999 2468 2699 2387 1201 2007 1886 661 2545 2527 285 + 2358 1796 954 + 789 2177 966 2481 1629 411 179 930 754 2061 841 687 957 1116 621 + 1236 636 263 374 506 985 1055 927 1804 1104 2429 390 232 1693 296 + 499 1359 448 1361 2370 9999999 353 488 1394 800 1428 1896 532 217 2479 + 423 825 1536 + 1154 2403 1241 2712 1817 176 340 1199 1014 2320 1146 874 1232 1392 791 + 1398 350 419 151 739 1116 1282 1204 2209 1436 2570 289 240 1959 237 + 591 1666 726 1490 2732 312 9999999 855 1610 1063 1665 2126 207 600 2664 + 754 1054 1852 + 514 1895 655 2265 1531 739 492 329 290 2007 671 615 962 939 389 + 708 1052 549 850 682 1173 592 708 1878 1139 2305 1015 636 1528 843 + 313 1391 469 1078 2343 529 887 9999999 1286 361 1114 1923 979 340 2437 + 474 928 1576 + 1232 1141 943 1222 534 1485 1372 1439 1153 879 678 862 390 611 949 + 1157 1610 1385 1532 829 382 1057 770 734 483 1183 1580 1504 754 1350 + 1357 255 1001 641 1214 1312 1653 1420 9999999 1030 1168 709 1451 1329 1247 + 1090 653 364 + 262 1623 397 1915 1050 898 682 573 237 1775 342 439 636 698 196 + 638 1092 683 1125 578 695 364 487 1644 667 1815 1011 842 1238 1022 + 543 1179 456 771 2058 795 910 449 1058 9999999 812 1411 1112 610 2066 + 417 574 1033 + 798 1070 476 1489 790 1729 1582 940 954 1562 957 922 957 695 1068 + 567 1847 1458 1743 1210 1096 627 846 1502 838 1554 1835 1462 709 1766 + 1195 1150 1063 496 1727 1452 1803 1194 997 833 9999999 1159 1857 1385 1819 + 1098 1074 907 + 1536 598 1201 631 449 2195 2058 1776 1767 494 1261 1519 1138 900 1547 + 1459 2231 1924 2156 1470 993 1388 1175 407 955 569 2225 2090 501 2123 + 2002 841 1592 988 699 1868 2137 1899 658 1530 1127 9999999 2060 1916 745 + 1667 1272 510 + 1176 2389 1379 2717 1694 332 408 1260 1022 2321 1004 879 1079 1384 814 + 1588 250 496 217 685 1100 1308 1175 1985 1293 2589 236 498 1912 170 + 709 1428 781 1574 2471 530 212 851 1544 1096 1675 2133 9999999 708 2454 + 706 907 1672 + 619 2085 990 2459 1541 520 280 793 507 2204 821 644 1092 1176 420 + 948 636 231 605 629 1046 945 831 1990 1162 2387 600 416 1766 494 + 197 1483 420 1173 2410 250 615 445 1441 539 1294 1902 590 9999999 2434 + 423 757 1531 + 2281 1127 1889 727 1131 2498 2445 2443 2350 594 1874 2030 1591 1659 2192 + 2056 2593 2501 2532 1979 1553 2056 1761 577 1529 595 2553 2613 1292 2555 + 2474 1123 2106 1632 324 2448 2712 2465 1183 2151 1793 795 2542 2526 9999999 + 2196 1783 1001 + 584 1919 727 2331 1424 610 491 761 514 1839 455 427 733 833 282 + 933 769 376 712 433 886 636 694 1782 964 2210 748 583 1400 675 + 375 1234 152 1078 2279 377 665 332 1160 485 1090 1641 631 415 2342 + 9999999 645 1281 + 856 1456 670 1757 900 860 842 1110 831 1365 324 480 335 625 525 + 981 1008 896 1082 250 274 802 470 1140 486 1609 1062 832 1051 937 + 914 615 426 857 1856 786 1087 955 560 646 1048 1351 1035 809 1752 + 679 9999999 811 + 1209 724 957 1012 248 1750 1558 1373 1393 683 957 1018 588 633 1190 + 1169 1840 1656 1912 1112 811 1188 873 590 428 984 1759 1682 509 1743 + 1590 480 1202 703 1134 1594 1913 1515 346 1227 968 537 1714 1616 1145 + 1371 902 9999999 +EOF diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/pbm.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/pbm.txt new file mode 100644 index 0000000..38c5037 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/pbm.txt @@ -0,0 +1,2 @@ +30 +/Mallba/ProblemInstances/DNAFA-instances/x60189_4.dat diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/score.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/score.txt new file mode 100644 index 0000000..ff26d92 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/score.txt @@ -0,0 +1,39 @@ + 0 1 0 304 1 1 1 0 7 -163 247 1 2 1 1 0 0 2 0 1 1 1 2 1 1 107 0 1 3 1 1 0 1 286 1 3 0 1 1 + 1 0 1 1 -3 3 -1 331 -302 2 5 0 1 0 0 -1 -2 -2 2 281 0 -413 1 0 168 -2 2 0 -3 39 412 2 155 1 4 247 274 0 53 + 0 1 0 -2 225 0 2 1 0 -1 1 178 1 2 -2 -1 -2 -149 -3 -1 -2 2 1 366 -2 4 2 -2 -7 -2 -3 -363 -2 -2 -327 -1 -1 -353 -3 + 304 1 -2 0 -1 -27 -1 0 -1 -160 327 -3 43 -1 1 4 1 2 1 -1 1 -4 2 1 1 200 -1 1 1 1 1 2 1 283 -1 3 3 1 1 + 1 -3 225 -1 0 -2 -3 -3 -2 -1 0 1 0 -1 1 -1 -1 -279 -2 -2 2 0 -106 104 -2 1 2 -2 2 -1 -1 -252 0 -1 -65 0 -1 -250 -1 + 1 3 0 -27 -2 0 1 0 -2 -1 -14 -1 -346 1 -1 6 -88 -1 -241 -2 -1 1 0 1 -2 -276 1 -2 2 -2 -2 1 1 -1 -3 -1 0 3 3 + 1 -1 2 -1 -3 1 0 0 1 -1 -3 -1 2 -6 -414 0 -1 -2 -1 1 -301 2 99 1 1 1 271 6 1 -1 -1 -2 1 -1 1 -3 -2 -1 -1 + 0 331 1 0 -3 0 0 0 -302 0 1 0 1 0 0 1 2 2 3 185 0 -317 1 0 72 -4 2 0 0 2 316 2 155 0 0 247 178 0 3 + 7 -302 0 -1 -2 -2 1 -302 0 -26 2 -1 2 -4 -1 0 -1 -2 -1 -156 -1 288 -2 1 -43 1 1 -2 3 -1 -287 1 -306 -1 1 -377 -149 -1 -1 + -163 2 -1 -160 -1 -1 -1 0 -26 0 -103 2 1 -1 2 1 0 -1 0 -2 1 -1 -1 1 1 0 0 1 1 2 2 1 76 -289 -2 5 -2 2 2 + 247 5 1 327 0 -14 -3 1 2 -103 0 1 30 1 1 1 1 0 -2 1 2 0 1 0 -4 187 2 0 0 0 0 0 0 226 1 0 1 2 5 + 1 0 178 -3 1 -1 -1 0 -1 2 1 0 1 0 -2 -1 1 1 1 2 0 1 2 271 0 1 -1 -4 -309 161 1 -54 0 1 -316 -1 2 -44 23 + 2 1 1 43 0 -346 2 1 2 1 30 1 0 1 1 1 150 0 303 1 1 0 1 0 0 292 1 0 0 0 0 0 0 -2 1 0 1 1 0 + 1 0 2 -1 -1 1 -6 0 -4 -1 1 0 1 0 6 260 -251 2 -123 0 6 2 -1 0 0 1 -2 -300 0 2 -1 -2 0 -1 0 -3 -2 0 -1 + 1 0 -2 1 1 -1 -414 0 -1 2 1 -2 1 6 0 -1 1 1 3 2 301 -2 -79 0 0 1 -251 -6 0 1 1 2 0 1 2 3 2 0 1 + 0 -1 -1 4 -1 6 0 1 0 1 1 -1 1 260 -1 0 -306 2 -178 1 -2 -1 -1 0 0 -4 -2 -100 0 2 3 -2 0 0 1 1 1 -3 3 + 0 -2 -2 1 -1 -88 -1 2 -1 0 1 1 150 -251 1 -306 0 2 339 -1 1 -1 -1 1 1 18 -2 91 1 2 3 -2 1 1 -1 1 1 1 3 + 2 -2 -149 2 -279 -1 -2 2 -2 -1 0 1 0 2 1 2 2 0 -1 -1 1 -1 252 -28 1 2 115 3 1 1 1 176 1 2 -1 1 -1 174 1 + 0 2 -3 1 -2 -241 -1 3 -1 0 -2 1 303 -123 3 -178 339 -1 0 -1 1 -1 -1 1 1 171 0 1 1 2 2 1 1 1 -2 2 1 2 2 + 1 281 -1 -1 -2 -2 1 185 -156 -2 1 2 1 0 2 1 -1 -1 -1 0 0 -312 -1 0 324 1 1 -2 2 214 313 1 9 -1 -3 101 310 3 228 + 1 0 -2 1 2 -1 -301 0 -1 1 2 0 1 6 301 -2 1 1 1 0 0 -2 1 0 0 1 -138 -6 0 1 1 3 0 1 0 3 2 0 1 + 1 -413 2 -4 0 1 2 -317 288 -1 0 1 0 2 -2 -1 -1 -1 -1 -312 -2 0 1 -2 -199 1 1 -2 0 -70 -443 -2 -141 -2 3 -233 -305 1 -84 + 2 1 1 2 -106 0 99 1 -2 -1 1 2 1 -1 -79 -1 -1 252 -1 -1 1 1 0 -2 0 2 228 0 -2 0 0 3 -2 2 -1 2 -1 1 0 + 1 0 366 1 104 1 1 0 1 1 0 271 0 0 0 0 1 -28 1 0 0 -2 -2 0 0 1 -3 0 -100 1 1 -242 0 3 -420 0 2 -232 1 + 1 168 -2 1 -2 -2 1 72 -43 1 -4 0 0 0 0 0 1 1 1 324 0 -199 0 0 0 1 -3 -2 2 195 200 2 0 1 -3 0 204 3 209 + 107 -2 4 200 1 -276 1 -4 1 0 187 1 292 1 1 -4 18 2 171 1 1 1 2 1 1 0 0 1 -3 -2 -2 0 1 86 2 3 0 -2 -2 + 0 2 2 -1 2 1 271 2 1 0 2 -1 1 -2 -251 -2 -2 115 0 1 -138 1 228 -3 -3 0 0 1 1 -1 -1 -1 -3 -1 1 -2 -1 -1 -1 + 1 0 -2 1 -2 -2 6 0 -2 1 0 -4 0 -300 -6 -100 91 3 1 -2 -6 -2 0 0 -2 1 1 0 2 1 1 2 0 1 0 3 2 0 1 + 3 -3 -7 1 2 2 1 0 3 1 0 -309 0 0 0 0 1 1 1 2 0 0 -2 -100 2 -3 1 2 0 -141 1 1 0 -3 145 0 0 -3 -3 + 1 39 -2 1 -1 -2 -1 2 -1 2 0 161 0 2 1 2 2 1 2 214 1 -70 0 1 195 -2 -1 1 -141 0 71 -1 1 1 -1 1 75 1 291 + 1 412 -3 1 -1 -2 -1 316 -287 2 0 1 0 -1 1 3 3 1 2 313 1 -443 0 1 200 -2 -1 1 1 71 0 -1 140 1 -2 232 306 2 85 + 0 2 -363 2 -252 1 -2 2 1 1 0 -54 0 -2 2 -2 -2 176 1 1 3 -2 3 -242 2 0 -1 2 1 -1 -1 0 2 2 203 -1 1 378 -1 + 1 155 -2 1 0 1 1 155 -306 76 0 0 0 0 0 0 1 1 1 9 0 -141 -2 0 0 1 -3 0 0 1 140 2 0 3 0 285 2 0 1 + 286 1 -2 283 -1 -1 -1 0 -1 -289 226 1 -2 -1 1 0 1 2 1 -1 1 -2 2 3 1 86 -1 1 -3 1 1 2 3 0 -1 3 2 1 1 + 1 4 -327 -1 -65 -3 1 0 1 -2 1 -316 1 0 2 1 -1 -1 -2 -3 0 3 -1 -420 -3 2 1 0 145 -1 -2 203 0 -1 0 1 -2 193 4 + 3 247 -1 3 0 -1 -3 247 -377 5 0 -1 0 -3 3 1 1 1 2 101 3 -233 2 0 0 3 -2 3 0 1 232 -1 285 3 1 0 94 -2 1 + 0 274 -1 3 -1 0 -2 178 -149 -2 1 2 1 -2 2 1 1 -1 1 310 2 -305 -1 2 204 0 -1 2 0 75 306 1 2 2 -2 94 0 -1 89 + 1 0 -353 1 -250 3 -1 0 -1 2 2 -44 1 0 0 -3 1 174 2 3 0 1 1 -232 3 -2 -1 0 -3 1 2 378 0 1 193 -2 -1 0 2 + 1 53 -3 1 -1 3 -1 3 -1 2 5 23 0 -1 1 3 3 1 2 228 1 -84 0 1 209 -2 -1 1 -3 291 85 -1 1 1 4 1 89 2 0 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/x60189_4.dat b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/x60189_4.dat new file mode 100644 index 0000000..2420540 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/DNAFA-instances/x60189_4.dat @@ -0,0 +1,78 @@ +>frag0000 +caccatctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtg +>frag0001 +agcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcc +>frag0002 +agggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaacacgcaccgcctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcaaagcggccctgggggacggtccaggaaaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctcgtccacatcctcttgtggggctgaaaggtaatatagggggatacagagtttaagggtttaagggcaacttgctttgctggtgctgtcaacagaggtcatacatcaaatgcgcccctccaga +>frag0003 +catctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaagaatgggcttttc +>frag0004 +gctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctcgtccacatcctcttgtggggctgaaaggtaatatagggggatacagagtttaagggtttaagggcaacttgctttgctggtgctgtcaacagaggtcatacatcaaatgcgcccctccagagcaggctgagggctggggcagctttgagttcgccgttcagtgactcttggaataagagccggtgaggtatccccgagcccccgactgtactgctggcagagctgcactgttagaaacctccagaaggcaa +>frag0005 +gcccctgacacgcatcacctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcgaagtggccctgggggatggtccaggagaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagcggctcctcagggggctccggggcctcagtgctgagttccgtggggctgggggtctcttcctctgcagctgagaaaaggagatatagagaggatgccaggtgcctgggggatgtgctcaggtcttcaagggaaggagggagaaaccatggccactactgggtatgtgaggtcatttcagaaaagcccattcttggggctgggtgg +>frag0006 +gaattcccaacctcaggtgatccacccgcctcggcctcccaaaatgctaggattacaggcgtgaaccactgctcccagcccagaatttcttttttagcccacgtttttctagtgaaaataatacagcaacattatgtggaaagcttgaaaaacagaaaacaagaatctcatagtcctactttctcccccagctgccggcattaataacaatgtgtgtagtgcacattcccttcctgtattttgcatgcagaggctgttttaaagttgcaatcagtgttcataaagttcttggcacttccttttttgtacacaagtacattgtaatcattcacctcacggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttg +>frag0007 +agcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccct +>frag0008 +gctggtgaggagctggatccaggaacacaccccaggctctggcctcgggaggagtgtgctgagcttgttgcggagcaaagacagaagcccagtgaacaaaagatggcgaagagaccccagtgctgggaggccaggggtgcagaggccgagtggggctgtgctcaaaagagaggcggtgctggagggacagggagaggtggcctgggtgttgggaggtgggggtgaggtgggggctgagggcaggagggtcagggtgagggataggaaaggccacaggagaggagaggatgaagagctgtgctggaggggctgtgggcagcatcgtcctgctcttgggcactttgtgttttgtgacacatcctttctatgctgaactgaggagccagggacctcactgtccccacacgtgtctgtccaactccagaggatgaagccgagaccacccaagcagtg +>frag0009 +ccaaagagcaagagggtgaccctcccacggctcccaccctggggctgccatcatccactcacccgtcaccccaatgacagagatggggcccacgcgctggccaccgtggaagccgtacaggttcatcttgtatttatggtctggctccaggcctgagatggtgaccccgtcctcgtgccccggcacccgcaccgccttgggctgcccatccccattcctgtactggaccaggaagtggtcaaactggccctcgggaaccgtccaggacaggctgagggagtcaggggtggcatctgtcatggtcagctcccccaggcgaggcttgatggggggctcaggggtcatggtaggcactgcttgggtggtctcggcttcat +>frag0010 +tggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaa +>frag0011 +atgctctttctagcctcctggcctttgcaccagctgtgattatctgacacacttcaccttctctctaaagctgtcaccaagctaaggcatgcctggcctcaggtcctggctgtcccctgggtacccatgggcagggtgacttaggcgtccctgtctggtcctgacctgagccctgggcctccctatcacatgctcacccgcctttgcttcatttgctggattgcagcctgtctctccatgacatgtctttccataatgttgctatattcctttcactgtgagccccatcaagacagaaatatgtataggaaaatggtagagaagggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaac +>frag0012 +tgtcagttgagcaggaccacccagccccaagaatgggcttttctgaaatgacctcacatacccagtagtggccatggtttctccctccttcccttgaagacctgagcacatcccccaggcacctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgta +>frag0013 +gaattctttgctgaatgaacaaattggcccattggtgagaaaggtctgttcctattcctattccaatagtgggcttccagagtgtgcagtcgacgcgctgcccctcactgccttctgtcttccttcacggcccctagtcaactccacagagaaagcacactaccaggaatcagggacgcagaaaaattctcttcaacagatttcaaaagagggtccaattcctttgtcgtgaagaactttgctactcaaggggcgtgatcatgggccagcagcatccgcatcatttcttgttggaaatgcgagaatctctggccctagcccaaacctgttgaaccccaatctgcctcttagcaagatccccaagcatggaaacgtgcaaaagaagcccggctggtgagaatatttttgttttcatgaagttgcagagaaagcaacatcttctagggccatcttcctcact +>frag0014 +attaattttgttatagtgctttcaccgcaacgcatcaaataaccattgaaacgatgatgaatgctggttgtgtagccgtgaggtgaatgattacaatgtacttgtgtacaaaaaaggaagtgccaagaactttatgaacactgattgcaactttaaaacagcctctgcatgcaaaatacaggaagggaatgtgcactacacacattgttattaatgccggcagctgggggagaaagtaggactatgagattcttgttttctgtttttcaagctttccacataatgttgctgtattattttcactagaaaaacgtgggctaaaaaagaaattctgggctgggagcagtggttcacgcctgtaatcctagcattttgggaggccgaggcgggtggatcacctgaggttgggaattc +>frag0015 +tttcaaaagagggtccaattcctttgtcgtgaagaactttgctactcaaggggcgtgatcatgggccagcagcatccgcatcatttcttgttggaaatgcgagaatctctggccctagcccaaacctgttgaaccccaatctgcctcttagcaagatccccaagcatggaaacgtgcaaaagaagcccggctggtgagaatatttttgttttcatgaagttgcagagaaagcaacatcttctagggccatcttcctcactcacaaacactcacctgtcacacccacggtggacaccgggcccacacgccgcccct +>frag0016 +ctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgtacggcctccacgaggggcggcgtgtgggcccggtgtccaccgtgggtgtgacaggtgagtgtttgtgagtgaggaagatggccctagaagatgttgctttctctgcaacttcatgaaaacaaaaatattctcaccagccgggcttcttttgcacgtttccatgcttggggatcttgctaagaggcagattggggttcaacaggtttgggctagggccagagattctcgcatttccaacaagaaatgatgcggatgctgctggcccatgatcacgccccttgagtagcaaagttcttcacgacaaaggaattggaccct +>frag0017 +ctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgagaattactttggctcctgacactatgtctcagttgccttctggaggtttctaacagtgcagctctgccagcagtacagtcgggggctcggggatacctcaccggctcttattccaagagtcactgaacggcgaactcaaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggca +>frag0018 +cctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgtacggcctccacgaggggcggcgtgtgggcccggtgtccaccgtgggtgtgacaggtgagtgtttgtgagtgaggaagatggccctagaagatgttgctttctctgcaacttcatgaaaacaaaaatattctcaccagccgggcttcttttgcacgtttccatgcttggggatcttgctaagaggcagatt +>frag0019 +gccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggat +>frag0020 +aaggaagtgccaagaactttatgaacactgattgcaactttaaaacagcctctgcatgcaaaatacaggaagggaatgtgcactacacacattgttattaatgccggcagctgggggagaaagtaggactatgagattcttgttttctgtttttcaagctttccacataatgttgctgtattattttcactagaaaaacgtgggctaaaaaagaaattctgggctgggagcagtggttcacgcctgtaatcctagcattttgggaggccgaggcgggtggatcacctgaggttgggaattc +>frag0021 +gatggggtggcagggagcctggaggcagcgaggccagtaggcagttggtggccctggtgagaggtgacagtggctcaaactaggatcggggactggaggtggggtaggaaggtatccaggggaattcagggtaaagatgctctgaggctgctggcagctggtgaggagctggatccaggaacacaccccaggctctggcctcgggaggagtgtgctgagcttgttgcggagcaaagacagaagcccagtgaacaaaagatggcgaagagaccccagtgctgggaggccaggggtgcagaggccgagtggggctgtgctcaaaagagaggcggtgctggagggacagggagaggtggcctgggtgttgggaggtgggggtgaggtgggggctgagggcaggagggtcagggtgagggataggaaaggccacaggagaggagagga +>frag0022 +acggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttgtgttcctgacacatctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgagaattactttggctcctgacactatgtctcagttgccttctggaggtttctaacagtgcagctctgccagcagtacagtcgggggctcggggatacctcaccggctcttattccaagagtcactgaacggcgaactca +>frag0023 +gtctctccatgacatgtctttccataatgttgctatattcctttcactgtgagccccatcaagacagaaatatgtataggaaaatggtagagaagggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaacacgcaccgcctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcaaagcggccctgggggacggtccaggaaaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctc +>frag0024 +gccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctc +>frag0025 +caccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaagaatgggcttttctgaaatgacctcacatacccagtagtggccatggtttctccctccttcccttgaagacctgagcacatcccccaggcacctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccaggg +>frag0026 +aatctcatagtcctactttctcccccagctgccggcattaataacaatgtgtgtagtgcacattcccttcctgtattttgcatgcagaggctgttttaaagttgcaatcagtgttcataaagttcttggcacttccttttttgtacacaagtacattgtaatcattcacctcacggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttgtgttcctgacacatctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgag +>frag0027 +gcatttccaacaagaaatgatgcggatgctgctggcccatgatcacgccccttgagtagcaaagttcttcacgacaaaggaattggaccctcttttgaaatctgttgaagagaatttttctgcgtccctgattcctggtagtgtgctttctctgtggagttgactaggggccgtgaaggaagacagaaggcagtgaggggcagcgcgtcgactgcacactctggaagcccactattggaataggaataggaacagacctttctcaccaatgggccaatttgttcattcagcaaagaattc +>frag0028 +gtgcccttctctaccattttcctatacatatttctgtcttgatggggctcacagtgaaaggaatatagcaacattatggaaagacatgtcatggagagacaggctgcaatccagcaaatgaagcaaaggcgggtgagcatgtgatagggaggcccagggctcaggtcaggaccagacagggacgcctaagtcaccctgcccatgggtacccaggggacagccaggacctgaggccaggcatgccttagcttggtgacagctttagagagaaggtgaagtgtgtcagataatcacagctggtgcaaaggc +>frag0029 +ctgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggatgagatactcaccgtaaaggacaccccactcaatcctcagtgcctctcacgtgccatgctctttctagcctcctggcctttgcaccagctgtgattatctgacacacttcaccttctctctaaagctgtcaccaagctaaggcatgcctggcctcaggtcctggctgtcccctgggtacccatgggcagggtgacttaggcgtccctgtctggtcc +>frag0030 +cctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatcc +>frag0031 +tcaaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggcacagagccccagggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcctgggcgcaag +>frag0032 +gtcagctcccccaggcgaggcttgatggggggctcaggggtcatggtaggcactgcttgggtggtctcggcttcatcctctggagttggacagacacgtgtggggacagtgaggtccctggctcctcagttcagcatagaaaggatgtgtcacaaaacacaaagtgcccaagagcaggacgatgctgcccacagcccctccagcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactc +>frag0033 +cacccctgactccctcagcctgtcctggacggttcccgagggccagtttgaccacttcctggtccagtacaggaatggggatgggcagcccaaggcggtgcgggtgccggggcacgaggacggggtcaccatctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtc +>frag0034 +ggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcctgggcgcaagtacaagatgcacctgtacggcctccacgaggggcggcgcctgggcccggtgtctgccgtgggcgtcacaggtgagtgagtgtgggtggggcagggttggaagacagccctagaaaatgtgcccttctctaccattttcctatacatatttctgtcttgatggggctcacagtgaaaggaatatagcaacattatggaaagacatgtcatggagagacaggctgcaatccagcaaatgaagcaaaggcgggtgagcatgtgat +>frag0035 +ttcatcctctggagttggacagacacgtgtggggacagtgaggtccctggctcctcagttcagcatagaaaggatgtgtcacaaaacacaaagtgcccaagagcaggacgatgctgcccacagcccctccagcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcac +>frag0036 +tcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccat +>frag0037 +aaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggcacagagccccagggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcc +>frag0038 +cctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggatgagatactcaccgtaaaggacaccccactcaatcctcagtgcctctcacgtgccatgctctttctagcctcctggcc diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/format.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/format.txt new file mode 100644 index 0000000..dc630e1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/format.txt @@ -0,0 +1,4 @@ +// number of variables, number of clauses and number of literals per clause. +// clause 1 (finalized in 0), if literal < 0 then the literal is negated. + +// clause N (finalized in 0), if literal < 0 then the literal is negated. diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat1.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat1.txt new file mode 100644 index 0000000..f8aa7fe --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat1.txt @@ -0,0 +1,44 @@ +10 43 3 +-4 -1 5 0 +-1 -9 -10 0 +-5 -3 -8 0 +-4 -8 -5 0 +2 6 7 0 +-9 -1 -10 0 +5 -3 -9 0 +1 -3 -5 0 +7 2 -4 0 +-7 3 4 0 +-2 1 -9 0 +-8 1 3 0 +3 6 7 0 +-1 -3 -2 0 +4 7 -2 0 +-8 -7 -3 0 +4 3 2 0 +-5 -4 1 0 +-9 10 -8 0 +-6 2 8 0 +-7 -8 5 0 +-7 -5 3 0 +7 9 -10 0 +1 -6 -3 0 +1 -9 6 0 +10 9 4 0 +-8 3 7 0 +8 7 -3 0 +-8 4 9 0 +8 -5 4 0 +8 10 1 0 +-1 -7 8 0 +6 2 5 0 +6 2 10 0 +2 -6 4 0 +-3 9 -1 0 +9 1 -10 0 +10 -5 -8 0 +-10 6 1 0 +1 7 2 0 +-6 3 2 0 +-1 -9 8 0 +-5 2 -10 0 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat2.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat2.txt new file mode 100644 index 0000000..806241f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MAXSAT-instances/sat2.txt @@ -0,0 +1,4301 @@ +1000 4300 3 +881 -647 537 0 +-739 396 282 0 +-43 -487 -52 0 +-643 205 796 0 +939 -885 -829 0 +-361 576 421 0 +-193 904 -238 0 +-940 902 26 0 +-177 -783 257 0 +439 942 675 0 +-794 714 -977 0 +310 -524 523 0 +-762 -494 260 0 +-578 305 502 0 +-805 -630 547 0 +729 855 -76 0 +-168 -754 667 0 +965 -418 93 0 +-668 -824 -495 0 +286 976 339 0 +776 -809 -157 0 +395 -120 838 0 +412 895 703 0 +-472 -479 -19 0 +-65 -918 945 0 +-682 -47 -590 0 +-956 996 316 0 +-969 120 222 0 +809 938 995 0 +-882 131 -976 0 +34 61 -359 0 +475 182 -67 0 +105 -391 986 0 +616 -867 -339 0 +-830 236 752 0 +-415 124 903 0 +-473 585 681 0 +203 -11 380 0 +-874 -126 -568 0 +498 -850 -74 0 +435 -113 -261 0 +-690 542 148 0 +-800 -657 752 0 +-624 269 526 0 +794 177 512 0 +-620 -987 819 0 +292 -87 455 0 +-945 758 946 0 +-723 421 908 0 +131 -977 369 0 +-811 -172 875 0 +971 410 -522 0 +287 474 -157 0 +753 458 491 0 +-265 -653 -269 0 +743 890 -606 0 +-207 555 211 0 +-367 799 403 0 +869 559 -407 0 +33 657 488 0 +834 -663 646 0 +-318 -109 804 0 +-235 572 452 0 +-257 -977 984 0 +386 -388 800 0 +-879 -50 131 0 +91 936 -258 0 +215 -310 -748 0 +911 842 670 0 +-514 442 496 0 +8 -111 35 0 +616 -77 325 0 +266 796 918 0 +-22 -261 -317 0 +-654 827 647 0 +48 -267 -905 0 +-921 418 407 0 +685 930 -196 0 +593 379 212 0 +-407 812 805 0 +-983 -942 919 0 +-138 32 678 0 +-306 764 -898 0 +-752 637 573 0 +916 332 -598 0 +890 350 -859 0 +-216 -821 -218 0 +-497 -981 -276 0 +-681 -893 -12 0 +765 -862 -222 0 +-740 6 666 0 +4 145 -59 0 +825 217 14 0 +135 889 -870 0 +-147 -85 -563 0 +298 -876 929 0 +-341 943 997 0 +329 -258 299 0 +-41 911 -906 0 +439 716 450 0 +-300 709 -704 0 +-363 125 260 0 +-442 776 474 0 +-615 -612 593 0 +233 -271 40 0 +661 248 -981 0 +-549 736 228 0 +565 -795 97 0 +706 -314 881 0 +-513 -476 -125 0 +54 721 822 0 +355 -327 -772 0 +-94 588 284 0 +-977 697 485 0 +-144 560 -671 0 +112 -780 324 0 +649 35 -134 0 +84 912 -265 0 +-705 21 858 0 +-224 -991 491 0 +930 -610 -668 0 +-956 -723 -845 0 +-694 798 527 0 +-208 726 594 0 +-151 311 279 0 +-347 -499 994 0 +679 195 -34 0 +-214 829 -895 0 +771 -106 -532 0 +684 855 942 0 +-323 552 -191 0 +-412 -8 -319 0 +327 -117 702 0 +-752 -663 234 0 +427 -92 846 0 +662 -736 -344 0 +164 774 -856 0 +-303 818 -889 0 +-791 -899 477 0 +-786 626 791 0 +-185 -589 -126 0 +964 314 466 0 +175 -299 -442 0 +-384 -545 -365 0 +-584 -719 -906 0 +901 -305 51 0 +-5 671 -804 0 +-895 417 55 0 +579 -693 586 0 +259 863 -872 0 +-176 -933 213 0 +829 437 24 0 +-322 -321 910 0 +-522 -696 641 0 +-682 -538 202 0 +108 450 798 0 +254 505 663 0 +-672 -420 116 0 +-652 -294 759 0 +-196 987 -572 0 +-219 -576 -261 0 +357 -975 -458 0 +164 -44 726 0 +-508 909 286 0 +-201 97 594 0 +-218 -198 776 0 +669 199 -655 0 +-146 822 360 0 +838 -958 372 0 +733 718 412 0 +-445 835 -924 0 +554 -488 155 0 +365 -834 -230 0 +-735 364 348 0 +540 -162 803 0 +-547 113 374 0 +-242 -569 -572 0 +-121 501 -174 0 +213 -815 -942 0 +370 758 492 0 +889 -733 -256 0 +636 -149 273 0 +543 176 -58 0 +92 941 402 0 +-683 -952 924 0 +788 -686 -56 0 +849 -866 155 0 +-121 837 323 0 +-578 866 277 0 +62 -504 857 0 +192 807 -944 0 +647 -350 -468 0 +816 967 -910 0 +-48 -745 285 0 +-894 -521 -397 0 +374 -616 905 0 +-968 -290 -854 0 +-770 747 -777 0 +610 779 -278 0 +-704 -452 964 0 +51 -774 -681 0 +532 -752 -528 0 +-738 433 -319 0 +17 635 -456 0 +-969 709 390 0 +68 317 -980 0 +-502 95 462 0 +-952 -920 -127 0 +280 -820 102 0 +466 635 -896 0 +446 967 -261 0 +-672 -626 396 0 +-609 392 103 0 +826 383 740 0 +-404 218 281 0 +112 -548 941 0 +-463 -408 975 0 +449 245 748 0 +-657 -752 668 0 +395 -915 739 0 +-246 100 -469 0 +975 388 814 0 +-669 -738 -465 0 +-199 203 336 0 +-85 -167 -662 0 +455 -789 475 0 +514 427 -915 0 +806 -825 -635 0 +720 -228 -179 0 +-941 -82 -700 0 +228 -256 -547 0 +374 732 -204 0 +-927 -79 58 0 +-535 -860 -669 0 +391 674 817 0 +-36 -15 -318 0 +-690 -538 -206 0 +-824 418 685 0 +-981 512 -849 0 +-268 -343 952 0 +-914 -720 -827 0 +173 -697 -115 0 +-95 628 -419 0 +-10 521 -459 0 +-539 236 396 0 +-922 -709 740 0 +-248 -746 679 0 +215 511 503 0 +-799 -121 -631 0 +-438 300 -651 0 +-76 287 135 0 +-566 186 706 0 +944 -756 230 0 +-950 264 -581 0 +113 953 821 0 +270 -214 192 0 +-442 145 -143 0 +-951 -931 349 0 +499 903 331 0 +-618 -654 112 0 +-287 -662 -243 0 +440 -691 -429 0 +-374 -370 -707 0 +-559 -883 -214 0 +988 439 471 0 +-239 -13 -732 0 +-997 593 751 0 +287 324 -135 0 +-624 -341 -298 0 +-796 851 -884 0 +198 -191 -81 0 +-71 -647 -421 0 +840 -87 56 0 +-710 465 -8 0 +-465 787 375 0 +573 524 232 0 +-373 -775 28 0 +7 516 -771 0 +-623 -951 770 0 +-152 841 656 0 +741 387 510 0 +49 287 642 0 +-202 -881 -389 0 +-265 -953 -752 0 +-756 -927 -479 0 +-422 227 25 0 +-162 -663 659 0 +-878 935 999 0 +86 982 -458 0 +781 515 510 0 +225 289 890 0 +929 -495 -377 0 +-857 866 -433 0 +436 221 530 0 +-750 8 -24 0 +-413 860 121 0 +609 375 321 0 +850 950 -27 0 +432 -539 -267 0 +-677 242 326 0 +-157 21 -736 0 +-812 -679 726 0 +787 856 -859 0 +-874 50 626 0 +-884 248 127 0 +-716 84 606 0 +825 382 308 0 +-922 -917 250 0 +625 -410 514 0 +144 -975 -311 0 +-570 115 -736 0 +-20 -584 179 0 +373 -515 -166 0 +705 985 226 0 +-707 816 -140 0 +535 -60 441 0 +800 459 -568 0 +50 -180 630 0 +365 715 -819 0 +17 -379 -454 0 +828 178 -957 0 +-383 -741 -258 0 +-740 -336 736 0 +178 -870 417 0 +375 205 216 0 +402 73 -492 0 +-361 63 -409 0 +-996 -741 152 0 +-981 411 808 0 +-875 -71 -26 0 +-448 627 -161 0 +-25 -808 -657 0 +866 -202 -348 0 +-963 -713 671 0 +-464 -642 215 0 +52 -312 -258 0 +96 -466 945 0 +-303 -957 -152 0 +-451 229 530 0 +-695 -547 835 0 +820 -646 294 0 +410 -921 15 0 +-40 520 837 0 +-610 -90 26 0 +-454 576 539 0 +469 -563 -62 0 +477 -897 -272 0 +394 -395 650 0 +551 318 -99 0 +406 -498 361 0 +-219 -348 -116 0 +551 82 -262 0 +-684 487 505 0 +-806 -903 -348 0 +-289 56 587 0 +-780 231 667 0 +-452 -44 68 0 +-586 96 -107 0 +-672 470 242 0 +178 287 46 0 +-648 -366 263 0 +777 126 435 0 +939 -289 -364 0 +830 -176 883 0 +-772 890 803 0 +-68 -429 -616 0 +659 -54 -227 0 +-502 53 999 0 +-430 -909 129 0 +-716 -970 -554 0 +57 -256 242 0 +-152 -255 -478 0 +-347 127 918 0 +127 328 368 0 +731 866 -936 0 +561 331 -525 0 +545 -188 -504 0 +919 765 -243 0 +-724 -864 -492 0 +645 425 -299 0 +949 -38 -968 0 +84 17 202 0 +-884 -28 -736 0 +-1 -410 -464 0 +493 467 -755 0 +642 -759 830 0 +-455 543 -47 0 +-523 885 -72 0 +-761 751 -575 0 +129 9 -836 0 +-621 -59 756 0 +-392 203 -919 0 +200 347 31 0 +-605 -359 525 0 +-869 -339 827 0 +871 -493 79 0 +721 -892 -406 0 +-140 -934 -96 0 +764 -796 -245 0 +365 1000 60 0 +-922 517 -990 0 +893 704 122 0 +819 -586 957 0 +170 184 491 0 +-72 664 381 0 +-1000 295 -918 0 +-868 525 -309 0 +534 -189 210 0 +461 -432 -990 0 +-605 71 -826 0 +527 -317 990 0 +974 -516 -442 0 +-443 -137 -84 0 +-713 -181 -555 0 +626 945 -996 0 +255 685 -306 0 +214 744 -786 0 +-183 -19 -812 0 +-704 472 678 0 +-321 -540 83 0 +277 953 128 0 +-693 -432 -452 0 +-59 -145 41 0 +135 -220 -865 0 +-601 122 -557 0 +-162 -877 238 0 +-373 -649 -579 0 +982 -445 -623 0 +-172 797 687 0 +138 -288 -868 0 +221 668 -570 0 +180 254 -469 0 +39 -766 657 0 +56 -465 773 0 +599 -183 127 0 +-263 81 169 0 +-74 432 -813 0 +-487 -756 -126 0 +-288 -285 -552 0 +-873 52 760 0 +221 631 -550 0 +-812 -310 -242 0 +-328 -141 -278 0 +-792 441 41 0 +51 983 -547 0 +-993 -150 -613 0 +352 564 -483 0 +123 389 -989 0 +-52 830 -364 0 +680 -189 46 0 +-241 634 -130 0 +-720 -401 -297 0 +731 -349 -736 0 +6 -452 8 0 +927 -875 911 0 +309 344 -112 0 +-326 610 -426 0 +843 -699 978 0 +546 118 856 0 +-397 -455 262 0 +653 914 -500 0 +480 848 130 0 +-304 679 672 0 +-765 984 -907 0 +-847 425 -46 0 +199 -727 -716 0 +-350 -281 -804 0 +394 851 -540 0 +-267 -334 -282 0 +339 754 558 0 +-835 -603 155 0 +628 -96 832 0 +-532 899 142 0 +-51 909 -248 0 +-913 20 -577 0 +-688 668 -529 0 +-725 430 198 0 +-887 -454 849 0 +-753 39 177 0 +-584 104 -805 0 +75 296 983 0 +-28 919 -18 0 +68 -848 -550 0 +185 -922 415 0 +-762 873 -367 0 +181 -79 -468 0 +709 -685 410 0 +600 553 -718 0 +-568 -757 309 0 +483 682 -439 0 +-923 847 -668 0 +-513 -668 392 0 +304 -813 880 0 +410 -179 -943 0 +205 -615 -377 0 +354 -131 -917 0 +614 -715 -891 0 +-150 -794 -375 0 +-970 376 325 0 +514 -584 -824 0 +-311 -847 -247 0 +919 -867 433 0 +273 872 -788 0 +958 9 -279 0 +-674 546 -261 0 +-954 678 -774 0 +-739 232 -328 0 +-196 -416 272 0 +338 921 900 0 +-655 -872 -286 0 +-232 -974 399 0 +-772 -199 -428 0 +-553 -778 306 0 +289 -84 151 0 +-483 866 -897 0 +-399 692 844 0 +-35 423 624 0 +-461 -88 -231 0 +-211 -956 -462 0 +-966 -994 40 0 +990 -149 813 0 +-228 853 913 0 +39 -330 -785 0 +-942 -726 -9 0 +-754 -122 -194 0 +539 503 710 0 +-123 461 -815 0 +425 -169 362 0 +3 -954 -383 0 +-538 -374 -8 0 +217 -318 51 0 +299 -499 -919 0 +-452 -121 -674 0 +211 -463 980 0 +-342 563 514 0 +839 691 814 0 +8 646 -632 0 +-487 -231 -401 0 +-479 -206 335 0 +-629 852 354 0 +950 -48 -406 0 +954 -977 415 0 +-315 -858 866 0 +-912 -799 -376 0 +-509 519 964 0 +-550 99 -996 0 +-173 342 483 0 +-677 -525 -828 0 +933 858 23 0 +425 166 -174 0 +-879 -970 -171 0 +618 -303 -364 0 +-76 507 512 0 +762 -604 947 0 +-188 256 -232 0 +730 -854 811 0 +338 -535 606 0 +-24 -772 102 0 +-132 -947 -454 0 +993 -344 476 0 +596 -856 -965 0 +-814 70 -553 0 +229 659 751 0 +38 473 696 0 +928 222 337 0 +-795 -524 -700 0 +-183 281 -516 0 +-169 249 -378 0 +394 -292 941 0 +-200 -806 -739 0 +33 777 358 0 +92 -168 162 0 +-995 -880 -189 0 +181 -495 428 0 +358 45 849 0 +-579 275 -391 0 +116 -466 -982 0 +923 513 -194 0 +-965 -325 -741 0 +-238 -655 643 0 +767 246 257 0 +-199 -826 -318 0 +-728 656 -603 0 +-395 -279 885 0 +259 -342 63 0 +-370 -928 -388 0 +556 544 348 0 +-886 115 788 0 +70 -668 690 0 +-55 -680 -474 0 +814 457 899 0 +-15 239 953 0 +249 184 -6 0 +-608 611 735 0 +-761 468 324 0 +60 -86 -731 0 +363 38 105 0 +-53 -780 953 0 +-140 953 -163 0 +464 -410 438 0 +221 151 438 0 +98 415 698 0 +36 489 -655 0 +998 332 580 0 +-326 -971 105 0 +927 -857 499 0 +-677 -593 -779 0 +-622 -24 457 0 +-22 452 364 0 +-844 -647 194 0 +-101 -348 36 0 +115 -547 970 0 +-202 -261 -878 0 +272 -286 -125 0 +-722 -773 -601 0 +-796 250 273 0 +-834 -265 766 0 +-799 773 -680 0 +-296 841 980 0 +-902 -855 -699 0 +-301 -130 238 0 +799 -916 917 0 +-944 -681 731 0 +606 729 751 0 +649 67 582 0 +-267 -909 -979 0 +816 -889 650 0 +-716 -205 228 0 +530 -161 302 0 +175 823 -319 0 +-344 -944 -701 0 +433 272 -254 0 +94 113 -130 0 +806 -399 -508 0 +-880 897 -456 0 +-288 602 -793 0 +-999 92 362 0 +98 581 698 0 +-994 -428 -524 0 +-565 -967 -848 0 +97 814 -999 0 +842 -904 -899 0 +-61 627 437 0 +340 -977 371 0 +-220 302 336 0 +831 -591 251 0 +107 957 -949 0 +-552 -601 988 0 +-630 348 167 0 +-519 -587 404 0 +783 809 -377 0 +345 -315 -918 0 +-904 346 584 0 +-785 -201 -381 0 +-679 854 -334 0 +-117 367 836 0 +-274 -329 891 0 +-940 429 22 0 +341 -974 768 0 +-972 494 14 0 +-988 -457 -613 0 +997 -391 607 0 +-188 667 -874 0 +-468 814 927 0 +950 -677 -438 0 +-839 -469 691 0 +184 918 401 0 +-236 500 697 0 +-488 -595 -274 0 +390 -536 -162 0 +317 907 -247 0 +928 899 -770 0 +962 872 341 0 +-717 14 1000 0 +-805 -635 535 0 +-950 720 -883 0 +32 -360 390 0 +-176 -541 503 0 +-394 -550 279 0 +-387 -913 228 0 +-125 89 93 0 +329 99 -136 0 +435 -938 39 0 +856 -304 -915 0 +452 -818 129 0 +-18 -532 -493 0 +794 -408 -714 0 +-428 38 983 0 +992 609 -295 0 +-390 -477 574 0 +197 884 -530 0 +-79 -955 -958 0 +142 -455 465 0 +601 953 -622 0 +478 -678 947 0 +-443 -778 2 0 +608 -893 696 0 +421 565 300 0 +-164 140 -726 0 +-299 -320 214 0 +-237 1000 70 0 +136 -886 -613 0 +-145 802 692 0 +822 -641 -939 0 +-631 343 822 0 +554 -679 621 0 +176 432 523 0 +125 181 -41 0 +422 809 845 0 +691 -625 -281 0 +-605 967 -687 0 +809 155 -45 0 +-350 510 -722 0 +747 -816 -758 0 +301 -392 -3 0 +198 -856 -397 0 +-304 965 808 0 +-120 -412 641 0 +95 -903 702 0 +146 -932 776 0 +-231 -163 -696 0 +682 668 -939 0 +-819 460 451 0 +57 -799 -592 0 +-391 453 769 0 +-381 -877 -983 0 +686 595 68 0 +-800 -485 39 0 +396 803 821 0 +-727 -988 -37 0 +-883 66 805 0 +-966 432 -977 0 +-786 468 192 0 +-849 24 -514 0 +-67 690 153 0 +-526 -518 442 0 +27 631 -245 0 +701 211 -58 0 +514 243 904 0 +58 483 956 0 +-815 -870 -158 0 +-296 993 -476 0 +-913 -581 -512 0 +-497 -11 -2 0 +-127 118 767 0 +-655 -302 -514 0 +273 293 395 0 +145 -390 338 0 +-716 117 -563 0 +273 172 256 0 +449 -693 -283 0 +19 -907 -97 0 +-237 -163 -509 0 +99 -813 886 0 +924 3 51 0 +-107 -314 515 0 +-907 184 367 0 +850 539 800 0 +-457 714 420 0 +411 -604 367 0 +643 -791 636 0 +-613 -888 500 0 +526 -605 47 0 +-431 947 930 0 +-660 -860 148 0 +-129 269 753 0 +-488 130 -958 0 +-772 491 422 0 +-910 -339 461 0 +13 -143 504 0 +-414 406 643 0 +-284 182 772 0 +-271 211 -577 0 +946 139 114 0 +-524 -463 108 0 +-424 -688 111 0 +317 780 -384 0 +-3 -50 -678 0 +719 -15 969 0 +-287 -899 -66 0 +-74 187 -865 0 +-346 794 910 0 +869 -166 121 0 +347 -540 224 0 +-26 -281 600 0 +-849 -788 -906 0 +-880 -348 -128 0 +-19 904 -430 0 +715 -377 490 0 +406 230 675 0 +-495 -110 615 0 +474 315 180 0 +-883 672 -444 0 +578 -534 -662 0 +711 -112 -400 0 +-659 642 -144 0 +-693 676 52 0 +-258 716 997 0 +-38 -436 729 0 +-87 -622 -369 0 +516 309 4 0 +-425 657 -965 0 +870 -441 714 0 +-512 822 678 0 +-942 -982 -868 0 +-609 -78 -679 0 +44 -405 -463 0 +-334 -663 -534 0 +413 510 -451 0 +-846 865 475 0 +-559 -765 957 0 +178 222 -276 0 +-437 -645 -369 0 +-936 768 -601 0 +57 -136 554 0 +-374 28 -583 0 +-355 -926 -539 0 +-696 -381 -329 0 +243 720 287 0 +529 811 -790 0 +-961 889 -611 0 +113 542 89 0 +804 -345 532 0 +894 295 508 0 +-606 -894 70 0 +-898 -441 499 0 +-124 -372 -948 0 +223 -909 914 0 +-389 271 782 0 +345 -421 -32 0 +-137 771 -230 0 +587 -689 74 0 +642 351 -523 0 +-255 -297 673 0 +997 656 108 0 +-726 603 442 0 +390 -864 -452 0 +400 -532 -627 0 +215 876 656 0 +945 250 235 0 +651 -754 890 0 +254 -511 516 0 +53 623 -605 0 +500 798 696 0 +170 -84 933 0 +210 -168 150 0 +-765 871 514 0 +532 -793 -440 0 +-320 661 54 0 +422 121 -372 0 +-498 -693 -1 0 +-743 -352 327 0 +-917 -673 -251 0 +-172 -155 -598 0 +-356 -50 627 0 +-512 -498 46 0 +336 181 -852 0 +-585 -393 -178 0 +-849 -222 -478 0 +-677 -471 -645 0 +-729 -432 -517 0 +-147 -571 -730 0 +259 -368 270 0 +-461 524 -696 0 +-316 -700 758 0 +174 -966 -342 0 +-586 -16 114 0 +-208 -123 -490 0 +-864 851 -818 0 +-690 -524 -778 0 +301 -541 855 0 +664 -200 196 0 +-609 -207 452 0 +-991 451 -897 0 +429 168 954 0 +399 343 -962 0 +801 252 -200 0 +-457 -499 -480 0 +726 -1000 83 0 +675 -498 771 0 +282 631 394 0 +666 -595 90 0 +573 -538 121 0 +98 -901 925 0 +781 245 440 0 +-747 680 53 0 +557 -113 -787 0 +666 257 751 0 +-445 -232 251 0 +-582 -754 382 0 +-849 -303 255 0 +-950 -420 -313 0 +181 -5 29 0 +-16 -298 -965 0 +94 -785 -598 0 +618 -326 -549 0 +-337 474 283 0 +-476 -696 -349 0 +658 -423 526 0 +-973 880 943 0 +420 847 794 0 +565 833 -352 0 +254 755 312 0 +27 323 338 0 +709 996 479 0 +-636 851 -680 0 +102 -873 -263 0 +903 982 -37 0 +424 -366 805 0 +-468 755 638 0 +380 48 586 0 +427 212 414 0 +178 354 -673 0 +-156 -558 -192 0 +-670 -106 383 0 +-127 838 857 0 +195 -973 -987 0 +994 -891 112 0 +850 542 -238 0 +-124 -382 772 0 +-177 332 494 0 +-844 -511 818 0 +-843 -108 -721 0 +982 -463 899 0 +298 -810 -232 0 +-147 -17 -774 0 +-383 -592 748 0 +368 -321 882 0 +35 473 -855 0 +-578 927 654 0 +-620 683 694 0 +781 -54 169 0 +742 -256 -115 0 +622 -387 -123 0 +380 364 234 0 +133 659 80 0 +260 632 -265 0 +990 -596 -966 0 +944 694 995 0 +774 -212 -504 0 +-906 168 -75 0 +5 824 886 0 +55 982 34 0 +313 -87 -257 0 +792 575 586 0 +76 439 35 0 +449 542 330 0 +-95 111 971 0 +-433 -726 802 0 +-605 992 596 0 +-655 856 -631 0 +-413 600 -606 0 +165 843 -5 0 +883 -481 -210 0 +-579 -21 -533 0 +-232 -44 125 0 +434 -776 -171 0 +-509 -279 -29 0 +-910 795 -564 0 +-417 915 216 0 +67 983 -871 0 +565 -855 -675 0 +110 -387 461 0 +602 -88 -294 0 +-40 781 -826 0 +-996 612 -440 0 +916 -446 -606 0 +-947 684 -618 0 +48 694 7 0 +-497 866 58 0 +-915 77 710 0 +445 95 594 0 +710 682 -379 0 +581 -551 -419 0 +-873 -536 917 0 +-267 -794 51 0 +-890 -20 521 0 +969 104 529 0 +130 -929 237 0 +-426 216 93 0 +225 301 -589 0 +-825 -461 -918 0 +-426 82 901 0 +-878 185 -992 0 +510 -136 -850 0 +399 288 883 0 +-334 4 -807 0 +610 -512 -685 0 +-550 556 12 0 +-788 -492 8 0 +-473 190 -244 0 +-63 -446 598 0 +-774 -933 -219 0 +928 -311 -600 0 +-466 265 322 0 +817 -869 -57 0 +-887 940 63 0 +-603 862 -109 0 +-711 -845 -143 0 +415 226 192 0 +-275 321 607 0 +-954 312 600 0 +944 -377 -353 0 +320 -404 820 0 +58 -958 -858 0 +225 -289 -278 0 +-185 -797 -914 0 +486 123 895 0 +-863 -769 -812 0 +452 -322 -621 0 +-604 -591 649 0 +473 818 993 0 +265 912 150 0 +540 -107 -3 0 +3 -326 -128 0 +181 814 -41 0 +-646 -606 196 0 +-29 305 -547 0 +-966 -282 -398 0 +905 -994 -465 0 +89 -883 698 0 +724 -706 767 0 +691 -575 81 0 +-835 180 176 0 +-489 -205 585 0 +-718 -198 -28 0 +759 -647 406 0 +-740 -89 187 0 +-231 529 -319 0 +548 -387 406 0 +613 950 538 0 +-719 -331 -520 0 +616 728 871 0 +538 425 865 0 +-504 336 -716 0 +-497 274 133 0 +557 -132 -809 0 +-911 -226 -128 0 +484 -390 609 0 +-191 -396 81 0 +739 444 788 0 +-619 350 107 0 +-298 560 1000 0 +-179 -243 154 0 +476 -979 886 0 +275 -606 -674 0 +-495 220 -340 0 +-38 -653 14 0 +27 -676 832 0 +-121 820 403 0 +815 726 -337 0 +-409 878 -750 0 +-458 -618 129 0 +-619 -294 625 0 +-504 201 526 0 +394 447 974 0 +-774 -371 6 0 +589 -641 -846 0 +-803 257 934 0 +-516 -909 -306 0 +714 521 -782 0 +445 -19 -48 0 +627 -174 -483 0 +-257 -39 -527 0 +-873 762 -609 0 +445 -575 -844 0 +61 580 -816 0 +-86 578 317 0 +-35 -244 -127 0 +312 -836 786 0 +106 600 425 0 +-417 373 724 0 +98 -354 339 0 +482 -465 580 0 +-99 -730 311 0 +300 501 8 0 +-118 -332 -680 0 +-272 351 918 0 +94 798 833 0 +743 693 454 0 +560 656 -842 0 +-18 175 -643 0 +592 -423 830 0 +723 23 -507 0 +155 342 307 0 +-113 -738 454 0 +77 -430 -740 0 +171 283 -262 0 +-907 -866 -853 0 +-370 -881 429 0 +726 522 -817 0 +360 225 -648 0 +-974 47 492 0 +-993 -103 330 0 +-572 592 131 0 +-588 295 193 0 +-240 -954 -787 0 +941 797 417 0 +-263 245 326 0 +-227 -317 -550 0 +114 539 309 0 +204 223 -420 0 +538 400 -602 0 +-630 47 500 0 +-293 -59 189 0 +-599 50 -501 0 +-615 772 928 0 +-1000 343 -494 0 +953 189 -451 0 +-310 349 317 0 +86 427 151 0 +-577 -685 318 0 +-264 732 337 0 +-130 816 -496 0 +-784 -994 -921 0 +-258 128 277 0 +158 -86 -992 0 +-335 -683 -537 0 +720 901 -244 0 +863 -290 163 0 +-501 368 -681 0 +-221 -127 -1 0 +-584 677 -864 0 +981 -370 -623 0 +-114 602 -63 0 +-198 322 -981 0 +907 -533 -124 0 +153 299 -836 0 +-70 -659 -575 0 +-806 694 -823 0 +-333 -628 -151 0 +95 212 46 0 +259 575 -809 0 +228 902 -894 0 +-308 981 448 0 +-153 -341 20 0 +92 616 966 0 +326 -743 -859 0 +328 -843 347 0 +653 -428 -401 0 +212 717 -475 0 +306 -976 -469 0 +462 -974 -653 0 +379 -310 437 0 +712 -698 -483 0 +-989 126 -848 0 +478 -92 -769 0 +515 878 774 0 +-763 494 605 0 +399 314 122 0 +118 759 -195 0 +-61 905 -917 0 +-774 550 -693 0 +-657 -222 263 0 +-923 665 352 0 +655 -267 -936 0 +-297 -442 -448 0 +-347 -866 -174 0 +630 -866 -116 0 +-429 628 -274 0 +-751 -630 -352 0 +-9 666 -468 0 +-544 -140 -594 0 +356 705 506 0 +-645 -248 546 0 +-643 338 -37 0 +148 684 522 0 +475 336 -315 0 +198 302 194 0 +919 -795 921 0 +24 607 145 0 +-316 593 -52 0 +761 -292 -37 0 +456 766 682 0 +-814 -294 348 0 +-940 417 722 0 +712 -131 465 0 +-987 -449 -78 0 +987 -639 824 0 +288 -314 458 0 +686 528 -813 0 +-539 -282 81 0 +32 889 937 0 +579 -161 281 0 +-768 -518 626 0 +-386 -130 866 0 +-721 736 -414 0 +-137 725 -275 0 +140 -157 293 0 +-257 -183 -90 0 +832 -404 -111 0 +-123 -955 -792 0 +-149 999 66 0 +-660 -659 -151 0 +80 243 -258 0 +972 -247 -865 0 +436 961 254 0 +-120 -251 -492 0 +744 618 -748 0 +867 36 -93 0 +-629 -793 345 0 +-443 542 -187 0 +-40 -358 -592 0 +634 806 -122 0 +363 316 -634 0 +-229 338 -451 0 +-452 -798 391 0 +-29 174 -585 0 +15 -609 -136 0 +-751 659 -813 0 +-45 962 -593 0 +-475 439 -271 0 +-949 858 631 0 +931 233 917 0 +-824 74 -274 0 +529 -560 -464 0 +-355 892 -526 0 +193 787 734 0 +-949 583 727 0 +675 -296 -745 0 +652 279 639 0 +314 241 -815 0 +-227 -578 919 0 +653 -278 -718 0 +986 46 -146 0 +974 -651 693 0 +206 781 -523 0 +284 -712 930 0 +-977 458 -497 0 +-80 -825 769 0 +-578 85 -297 0 +202 420 -852 0 +-231 -589 -38 0 +-542 553 -661 0 +-258 -979 36 0 +59 821 159 0 +949 148 -411 0 +-469 383 -200 0 +-466 342 -232 0 +790 211 160 0 +-525 363 -196 0 +695 -77 -2 0 +123 -639 19 0 +-200 636 -671 0 +-898 19 798 0 +-593 -496 -32 0 +267 -125 91 0 +-98 -188 623 0 +602 685 -198 0 +-69 875 -387 0 +825 -289 227 0 +-285 -551 753 0 +875 -178 -57 0 +-682 -686 614 0 +-614 756 -241 0 +-654 -736 235 0 +-743 -845 375 0 +-893 763 246 0 +406 -233 610 0 +468 100 466 0 +-705 293 43 0 +-724 -697 634 0 +-517 -184 -743 0 +327 849 227 0 +694 869 -145 0 +447 222 975 0 +-512 -834 609 0 +258 -423 -681 0 +204 584 925 0 +532 27 -920 0 +-402 -786 938 0 +807 -401 -373 0 +-492 812 526 0 +-988 779 -926 0 +60 -858 -774 0 +340 -277 -547 0 +-747 329 601 0 +610 -826 624 0 +930 -596 -227 0 +395 742 563 0 +-171 970 396 0 +-655 -664 -701 0 +284 103 275 0 +-758 -824 -979 0 +191 868 891 0 +-290 -479 108 0 +410 -576 -176 0 +-473 223 -956 0 +-687 -127 386 0 +145 -189 713 0 +54 49 -507 0 +-700 510 230 0 +993 989 135 0 +843 -454 900 0 +663 478 584 0 +285 -784 288 0 +-199 404 -713 0 +-374 -147 238 0 +-58 21 -893 0 +289 963 -278 0 +-886 642 -185 0 +85 -130 77 0 +-927 210 166 0 +-587 418 145 0 +-652 878 -171 0 +952 207 826 0 +262 -953 -165 0 +-589 -404 174 0 +-878 411 705 0 +549 -187 -469 0 +-332 481 364 0 +155 214 -991 0 +-16 -928 160 0 +849 699 -388 0 +653 831 -22 0 +398 415 768 0 +-805 -288 -201 0 +947 -95 -942 0 +-872 59 553 0 +-386 -223 260 0 +202 82 881 0 +-44 -944 -670 0 +-886 -706 306 0 +-459 -774 -452 0 +-826 -361 -562 0 +-318 -732 512 0 +-716 -791 647 0 +-103 821 153 0 +-858 -938 114 0 +-973 826 870 0 +457 -326 -320 0 +301 808 556 0 +-502 960 146 0 +-456 -88 -144 0 +-915 -856 521 0 +-526 -71 -405 0 +626 24 -395 0 +919 171 191 0 +-122 -60 268 0 +862 -650 -735 0 +117 -511 949 0 +649 797 82 0 +-907 -919 136 0 +644 843 -849 0 +635 213 149 0 +970 204 460 0 +-216 -728 -159 0 +466 -989 693 0 +-106 200 -666 0 +-429 250 -980 0 +967 465 788 0 +-8 -939 803 0 +605 113 -797 0 +-37 -187 -164 0 +-380 -551 -387 0 +-705 758 800 0 +725 -470 267 0 +-909 -123 -996 0 +568 334 -211 0 +-530 608 551 0 +-615 173 444 0 +-592 -617 -158 0 +-793 684 -373 0 +-706 991 177 0 +727 -9 -204 0 +-608 486 174 0 +532 -570 876 0 +970 490 832 0 +232 884 -162 0 +-439 161 -565 0 +-692 235 -767 0 +437 831 -610 0 +-461 -672 878 0 +-371 -303 -258 0 +937 -162 -795 0 +-996 599 -98 0 +813 -466 395 0 +440 -851 469 0 +-64 -432 -555 0 +921 875 752 0 +303 -71 474 0 +-445 666 604 0 +-124 380 -322 0 +770 348 341 0 +-371 194 -14 0 +-668 -689 -275 0 +-800 -539 628 0 +419 -727 -587 0 +925 -376 714 0 +579 371 525 0 +539 216 789 0 +-143 87 -927 0 +-878 -248 -479 0 +459 164 -265 0 +522 783 554 0 +924 281 -484 0 +214 -322 779 0 +806 -425 470 0 +-248 518 349 0 +-210 139 -554 0 +3 -426 577 0 +934 659 548 0 +486 576 -801 0 +390 -402 21 0 +184 -113 927 0 +789 708 35 0 +405 -680 -962 0 +606 -958 -268 0 +-268 647 -56 0 +616 -257 221 0 +880 -310 -627 0 +847 501 -515 0 +-495 -289 178 0 +511 789 135 0 +609 -92 438 0 +-141 -357 -74 0 +-762 -434 305 0 +390 257 574 0 +119 199 -231 0 +935 -303 295 0 +871 -692 596 0 +538 -29 588 0 +-776 -502 553 0 +-711 908 -645 0 +879 224 -108 0 +931 -278 369 0 +849 -926 944 0 +854 395 234 0 +943 -46 -430 0 +-993 -624 -80 0 +-152 -868 252 0 +234 -473 -273 0 +370 984 691 0 +454 -708 -934 0 +720 230 967 0 +-941 -56 782 0 +-793 959 863 0 +286 -380 846 0 +-332 502 -455 0 +-66 865 974 0 +-123 -646 -318 0 +-341 -851 -344 0 +750 -837 915 0 +-341 -18 -318 0 +356 -624 -955 0 +-800 -669 500 0 +-700 204 -60 0 +992 -794 -819 0 +273 -734 -715 0 +579 -101 -436 0 +941 640 -156 0 +-802 182 402 0 +578 -763 -740 0 +-541 875 -13 0 +-27 -706 -7 0 +-43 -704 -442 0 +-853 -642 -420 0 +99 -351 664 0 +-293 22 -296 0 +-412 -847 997 0 +114 -709 413 0 +408 -91 323 0 +-502 868 402 0 +-300 122 689 0 +96 179 -814 0 +-308 -399 -289 0 +376 -656 -122 0 +605 -906 -148 0 +14 -495 909 0 +-646 66 -4 0 +959 833 -12 0 +198 -368 -16 0 +414 850 -363 0 +-982 -842 -365 0 +-524 283 -919 0 +-357 802 -733 0 +-772 391 161 0 +-611 239 494 0 +217 211 135 0 +965 -737 501 0 +499 351 112 0 +746 621 102 0 +-574 689 -533 0 +927 -66 -483 0 +316 715 -389 0 +-117 -336 -861 0 +-482 -365 -492 0 +905 -178 -653 0 +-183 812 -820 0 +-422 -555 -483 0 +550 678 -31 0 +282 778 -14 0 +-964 -549 -730 0 +-589 23 -595 0 +13 -923 691 0 +30 356 912 0 +-884 437 -563 0 +13 -996 931 0 +-243 -452 -74 0 +116 549 -237 0 +-222 285 668 0 +261 -888 -458 0 +216 -937 -525 0 +-14 185 119 0 +-785 272 -276 0 +487 -361 443 0 +987 -28 342 0 +-224 -505 -245 0 +620 655 525 0 +442 -103 128 0 +-248 759 81 0 +-762 22 389 0 +552 -145 262 0 +737 520 -131 0 +95 -295 473 0 +-396 -678 518 0 +-827 -55 -863 0 +-432 132 172 0 +-322 94 -33 0 +-290 665 626 0 +-966 275 -284 0 +-835 -508 174 0 +-940 417 175 0 +369 345 -267 0 +-350 429 201 0 +-489 31 185 0 +857 574 47 0 +204 -573 416 0 +-207 -298 220 0 +780 -991 -452 0 +-287 -775 -523 0 +374 484 -596 0 +449 -289 -755 0 +238 564 -251 0 +134 517 -908 0 +-811 540 66 0 +-237 20 -239 0 +934 222 -769 0 +-927 -23 -716 0 +348 981 260 0 +-595 901 537 0 +623 641 -823 0 +126 -620 782 0 +-566 -383 -658 0 +-717 -345 -164 0 +-22 -808 50 0 +613 42 65 0 +568 -207 -976 0 +-225 52 -836 0 +132 -463 -325 0 +-590 -386 -593 0 +634 -53 722 0 +648 -242 -410 0 +-352 -400 -642 0 +-69 -514 143 0 +181 -760 -465 0 +347 -875 -177 0 +882 -983 14 0 +121 103 -992 0 +-734 380 -322 0 +-986 -920 -926 0 +872 -781 565 0 +-800 903 329 0 +588 234 -960 0 +-411 375 584 0 +503 -210 189 0 +-209 767 610 0 +-992 925 622 0 +394 350 96 0 +-163 851 -778 0 +-852 -221 822 0 +796 -21 148 0 +-423 736 150 0 +696 -795 33 0 +-719 778 195 0 +-19 -625 894 0 +132 -883 -183 0 +-699 9 -923 0 +-956 -249 248 0 +-591 160 -988 0 +564 479 -399 0 +552 463 -840 0 +-422 -349 -200 0 +713 687 36 0 +-541 -817 -915 0 +221 552 -288 0 +-890 -578 143 0 +41 669 -195 0 +-35 107 -411 0 +948 -745 51 0 +581 628 719 0 +814 -304 -456 0 +-271 70 492 0 +115 214 -92 0 +216 -885 -306 0 +-942 804 242 0 +-121 716 577 0 +543 -146 -639 0 +-589 404 -435 0 +-590 120 854 0 +663 900 -211 0 +-337 -47 -359 0 +9 -628 -677 0 +-348 -648 -332 0 +680 475 388 0 +742 254 -732 0 +-521 127 466 0 +778 -310 -969 0 +-367 369 991 0 +95 -87 710 0 +741 -956 585 0 +-405 263 140 0 +580 557 54 0 +-121 -946 617 0 +-971 -99 -509 0 +-151 367 240 0 +-239 -522 464 0 +-545 -534 948 0 +373 -197 559 0 +762 907 -263 0 +684 -261 -537 0 +-134 3 -45 0 +558 -150 -902 0 +-296 356 -865 0 +983 581 -892 0 +714 185 -300 0 +576 -696 -504 0 +150 950 -809 0 +-56 420 -15 0 +-92 59 -925 0 +-670 -483 -284 0 +-762 -702 96 0 +975 759 294 0 +-857 -518 142 0 +937 -486 518 0 +-244 -585 -845 0 +-129 -834 216 0 +-439 385 926 0 +-377 29 -922 0 +-989 -502 -303 0 +892 -472 422 0 +-275 -561 26 0 +-747 887 -791 0 +277 -762 111 0 +-967 -891 286 0 +-470 -164 261 0 +762 527 -558 0 +159 -757 553 0 +944 270 558 0 +-398 -3 151 0 +-9 -715 80 0 +436 -15 -947 0 +872 -60 -213 0 +658 298 -787 0 +2 -784 94 0 +461 398 -696 0 +-550 982 -33 0 +199 -645 -154 0 +732 361 617 0 +-515 -386 -115 0 +-105 73 -165 0 +-145 165 48 0 +751 -977 -39 0 +995 -918 -892 0 +772 651 578 0 +110 311 -640 0 +-388 -139 693 0 +493 96 798 0 +-225 600 -253 0 +-226 -574 -530 0 +-86 156 599 0 +379 -15 299 0 +-953 622 967 0 +690 -454 -764 0 +688 -463 -265 0 +-123 -473 -282 0 +580 451 -242 0 +-642 523 -57 0 +-569 561 898 0 +754 -557 228 0 +121 547 734 0 +-133 -329 -314 0 +357 643 45 0 +-576 247 -677 0 +-819 8 -642 0 +312 496 941 0 +678 -196 46 0 +222 622 -17 0 +318 -303 757 0 +239 -649 219 0 +-944 -516 -448 0 +-336 293 290 0 +368 -868 915 0 +-84 11 -373 0 +40 -699 -964 0 +-202 849 -470 0 +627 -951 71 0 +441 238 354 0 +657 517 32 0 +-694 -306 -77 0 +-236 -977 821 0 +-304 -194 61 0 +236 -921 118 0 +-646 -644 691 0 +625 544 202 0 +785 992 -843 0 +504 -494 -713 0 +44 -556 192 0 +788 168 -891 0 +276 -183 940 0 +899 -163 705 0 +-440 172 -863 0 +-378 775 262 0 +285 670 583 0 +-235 35 414 0 +-106 117 -671 0 +999 -213 -140 0 +362 -775 977 0 +-882 197 -734 0 +-820 -969 -873 0 +335 920 740 0 +-919 350 -312 0 +-271 849 -548 0 +-643 -642 5 0 +-150 52 473 0 +-433 455 692 0 +-365 -631 918 0 +-390 -280 -124 0 +70 -544 -976 0 +-193 -235 -163 0 +-803 58 770 0 +-107 817 -323 0 +-67 954 124 0 +516 291 629 0 +-545 760 361 0 +483 591 -141 0 +650 294 -570 0 +-53 -855 -45 0 +57 -940 449 0 +471 -134 843 0 +-618 -732 -452 0 +-895 674 -939 0 +-970 -550 26 0 +220 493 874 0 +-948 159 602 0 +-777 195 898 0 +346 104 802 0 +-77 90 -923 0 +-441 -648 -480 0 +264 288 939 0 +385 780 267 0 +-195 -861 244 0 +143 713 -836 0 +-542 733 -739 0 +-138 -480 837 0 +527 -480 -38 0 +950 252 48 0 +993 -436 812 0 +563 705 -378 0 +-464 369 838 0 +843 378 571 0 +-391 634 680 0 +-799 -626 113 0 +599 -28 -285 0 +155 -210 981 0 +109 545 206 0 +-56 583 601 0 +969 -436 260 0 +-153 629 969 0 +-419 -514 -99 0 +-802 16 -922 0 +478 -996 778 0 +645 -389 -188 0 +-726 718 635 0 +-467 -116 272 0 +-669 105 -302 0 +763 -372 -778 0 +291 226 885 0 +-790 669 99 0 +889 -995 716 0 +130 777 926 0 +907 -699 268 0 +717 -940 718 0 +271 -425 247 0 +-502 -808 -866 0 +514 -958 709 0 +-984 841 16 0 +556 -188 999 0 +771 954 -758 0 +-182 -990 -919 0 +-44 475 -859 0 +-694 -423 -696 0 +296 -945 -131 0 +48 140 775 0 +365 275 615 0 +604 -950 757 0 +-861 -820 -377 0 +-763 -435 696 0 +-3 130 -493 0 +-567 281 -685 0 +-372 609 -445 0 +597 338 -679 0 +-400 588 68 0 +-909 536 -785 0 +455 -275 -102 0 +-362 -693 -529 0 +-709 -239 -513 0 +894 679 888 0 +-163 -479 -470 0 +459 264 -456 0 +-272 325 773 0 +297 -991 -119 0 +378 502 198 0 +-65 -466 57 0 +-411 -381 95 0 +970 862 699 0 +941 585 -538 0 +-239 41 35 0 +659 -210 826 0 +330 260 804 0 +509 80 -343 0 +-244 243 -134 0 +-338 -620 605 0 +698 -213 -768 0 +298 -923 762 0 +-995 41 -763 0 +309 -285 865 0 +996 104 619 0 +-896 -478 660 0 +-800 -904 -404 0 +546 812 101 0 +487 36 186 0 +-689 -218 -646 0 +482 490 304 0 +-503 -946 -116 0 +-722 52 430 0 +-905 -949 505 0 +776 969 866 0 +292 -613 957 0 +-26 -240 515 0 +429 58 -978 0 +149 86 -175 0 +982 -863 -415 0 +960 -343 717 0 +-836 688 102 0 +-762 609 -496 0 +117 630 -979 0 +-334 916 552 0 +-110 253 828 0 +-165 -873 -905 0 +670 -486 -898 0 +400 -529 -651 0 +-240 -334 -981 0 +-728 -869 -271 0 +957 101 -67 0 +226 -679 363 0 +-228 234 899 0 +-420 -43 965 0 +-535 -974 -97 0 +352 -162 737 0 +-141 -723 -553 0 +-76 -936 567 0 +943 -520 88 0 +683 557 827 0 +-939 49 551 0 +-645 -76 -797 0 +386 -913 -167 0 +694 -615 257 0 +-201 -294 154 0 +-492 -108 66 0 +-653 469 158 0 +717 294 444 0 +-881 -528 754 0 +-750 -23 -880 0 +26 578 -83 0 +933 386 742 0 +-913 910 -846 0 +489 -934 721 0 +-756 -611 -208 0 +155 446 977 0 +162 -899 -406 0 +951 355 290 0 +-810 -301 534 0 +618 846 -264 0 +36 755 -636 0 +-820 -709 736 0 +-442 304 -383 0 +449 66 -764 0 +-323 -635 298 0 +65 -624 254 0 +-43 -257 362 0 +348 -199 940 0 +-5 955 626 0 +-242 -3 651 0 +619 235 -881 0 +-203 -908 466 0 +526 874 -221 0 +-935 799 852 0 +618 -427 243 0 +724 -648 64 0 +576 -164 -662 0 +-772 710 -932 0 +986 578 -872 0 +-409 -920 573 0 +-126 499 335 0 +248 -533 -267 0 +-360 -755 862 0 +-811 1 577 0 +-73 -81 419 0 +-278 -367 600 0 +425 155 -186 0 +726 905 926 0 +798 -478 -415 0 +-134 301 -617 0 +709 12 175 0 +744 326 -578 0 +-114 473 79 0 +833 276 577 0 +26 808 -346 0 +-860 414 -158 0 +329 -731 -61 0 +874 -377 903 0 +223 108 -790 0 +-791 215 898 0 +404 341 -186 0 +996 972 490 0 +-126 -518 256 0 +-513 -754 604 0 +176 267 -31 0 +-196 -819 172 0 +834 -11 986 0 +-82 -849 -931 0 +450 746 -60 0 +159 196 615 0 +530 -75 318 0 +562 -316 112 0 +-206 -404 157 0 +-569 289 -530 0 +-152 -201 2 0 +497 749 -639 0 +314 -368 289 0 +698 -899 935 0 +768 -133 239 0 +991 -934 231 0 +-964 742 141 0 +-969 135 94 0 +232 519 158 0 +-547 939 736 0 +-176 202 -160 0 +-748 -999 -473 0 +219 134 -382 0 +666 989 607 0 +-55 87 -355 0 +-800 673 -722 0 +-38 -973 -751 0 +-373 32 787 0 +423 74 217 0 +-515 529 -444 0 +-426 969 378 0 +649 -218 -389 0 +316 767 -901 0 +417 -753 712 0 +-595 -300 635 0 +403 689 569 0 +-130 536 131 0 +-410 -758 621 0 +654 -826 -928 0 +514 210 217 0 +-417 -570 755 0 +-833 -491 945 0 +439 -381 -1 0 +895 183 18 0 +330 682 -26 0 +201 822 -550 0 +-52 269 -817 0 +877 -274 -264 0 +360 -688 172 0 +-43 152 -209 0 +-632 961 327 0 +361 -923 662 0 +739 952 176 0 +-196 -218 371 0 +752 -160 446 0 +-912 -881 168 0 +383 70 792 0 +110 268 -324 0 +719 988 -837 0 +554 127 290 0 +826 626 300 0 +161 28 471 0 +-934 921 -240 0 +-415 -19 -297 0 +-486 -734 114 0 +-839 890 -299 0 +303 565 833 0 +-679 -632 180 0 +582 -439 66 0 +961 -41 -820 0 +-59 594 -151 0 +-426 -422 -826 0 +-107 8 -235 0 +844 958 -838 0 +-210 -243 193 0 +307 258 418 0 +485 -57 492 0 +-150 110 -460 0 +870 320 219 0 +529 -410 885 0 +762 -967 -506 0 +-288 -458 -211 0 +-583 -974 -330 0 +-825 847 457 0 +-496 -597 -548 0 +931 560 334 0 +-457 -290 291 0 +754 796 555 0 +938 359 -334 0 +668 486 782 0 +-361 -678 840 0 +170 -13 213 0 +-808 156 300 0 +-98 -834 461 0 +-58 417 233 0 +-885 -719 144 0 +-193 -485 -392 0 +826 -876 391 0 +165 972 -472 0 +-317 -920 649 0 +839 -697 893 0 +-529 739 -156 0 +-271 -1 -952 0 +286 -535 452 0 +-555 201 -78 0 +-740 -765 -492 0 +62 778 -924 0 +-46 967 -621 0 +592 984 -29 0 +-310 235 262 0 +473 391 -87 0 +1000 -82 717 0 +344 -62 -844 0 +994 -174 -36 0 +-380 591 -160 0 +469 -781 -968 0 +596 -152 780 0 +-773 -133 493 0 +-240 -354 -26 0 +-701 -869 416 0 +-229 181 -618 0 +735 154 982 0 +-212 -277 -928 0 +-220 217 271 0 +-778 -487 -371 0 +350 -657 505 0 +148 11 746 0 +410 27 999 0 +-476 -998 -405 0 +922 507 606 0 +275 752 -410 0 +-510 842 680 0 +805 -316 -960 0 +672 -765 -771 0 +-200 -470 -162 0 +-232 -334 440 0 +593 -757 -676 0 +-6 -971 779 0 +71 -193 -913 0 +28 -832 230 0 +798 659 843 0 +-196 990 -932 0 +95 -37 600 0 +-137 -175 509 0 +20 778 -620 0 +-341 -644 841 0 +19 -235 -55 0 +-96 -828 905 0 +543 -279 218 0 +-939 341 859 0 +137 558 711 0 +-555 678 453 0 +-84 288 -306 0 +-959 510 592 0 +856 793 -623 0 +767 -821 922 0 +444 -810 -325 0 +-12 175 -942 0 +267 979 358 0 +-977 -660 838 0 +-126 840 -92 0 +-44 241 133 0 +-522 361 325 0 +212 921 -756 0 +399 915 945 0 +581 -631 507 0 +998 641 572 0 +585 -670 849 0 +-959 -846 -32 0 +-13 961 24 0 +-942 -807 -923 0 +-975 139 3 0 +-793 164 -591 0 +-496 -802 -512 0 +969 655 -929 0 +463 576 -823 0 +736 937 485 0 +800 496 -963 0 +799 -263 -445 0 +959 708 534 0 +706 -50 -414 0 +-615 339 -50 0 +973 -85 896 0 +559 510 260 0 +-714 783 689 0 +-581 -110 -257 0 +-429 162 -843 0 +285 -951 718 0 +19 -353 -510 0 +302 532 167 0 +-992 -477 -537 0 +-152 844 -819 0 +134 212 -215 0 +643 9 -709 0 +927 -821 443 0 +-101 -680 782 0 +333 440 100 0 +926 192 -269 0 +124 858 -413 0 +-376 151 938 0 +-605 -700 -461 0 +981 103 -770 0 +-258 -575 323 0 +-405 604 -353 0 +418 -485 709 0 +733 595 -892 0 +-845 289 -619 0 +-181 617 -216 0 +302 706 -102 0 +385 -631 -4 0 +805 492 820 0 +-543 -386 -876 0 +-344 -164 -420 0 +-286 841 -779 0 +426 -502 -9 0 +179 923 850 0 +-437 606 -278 0 +365 527 801 0 +-696 -505 517 0 +114 -324 746 0 +-926 204 919 0 +194 922 217 0 +446 -101 75 0 +-188 -287 -60 0 +-962 -856 -744 0 +587 -578 110 0 +-299 439 -728 0 +681 534 815 0 +-2 525 435 0 +286 154 -72 0 +374 121 -858 0 +-816 731 -479 0 +530 973 125 0 +541 835 -841 0 +-764 125 -742 0 +196 600 60 0 +-599 -312 -811 0 +458 -813 853 0 +430 -394 288 0 +400 81 17 0 +338 303 460 0 +108 652 446 0 +-630 507 566 0 +-981 314 635 0 +-800 -586 156 0 +-365 -246 704 0 +-118 -777 802 0 +352 -190 585 0 +921 -720 992 0 +331 486 891 0 +575 554 -577 0 +330 29 98 0 +-245 961 -111 0 +-510 588 799 0 +474 -321 -565 0 +137 -57 839 0 +843 -508 243 0 +342 -242 -315 0 +48 -370 -193 0 +195 -44 168 0 +-796 619 -913 0 +908 965 408 0 +-935 924 259 0 +-644 -817 -387 0 +840 903 456 0 +-737 656 175 0 +177 -355 651 0 +-446 -660 -34 0 +-726 -333 772 0 +842 900 -545 0 +102 456 -143 0 +126 311 897 0 +14 937 106 0 +833 -951 796 0 +-361 -766 -377 0 +-782 -110 -786 0 +-408 -150 -921 0 +-124 -101 467 0 +749 -433 -126 0 +931 446 -485 0 +4 754 890 0 +277 -509 661 0 +263 -271 550 0 +-36 342 -246 0 +832 29 -235 0 +-877 -603 -265 0 +-543 253 -342 0 +-997 -658 957 0 +572 360 742 0 +-960 350 739 0 +-968 -221 206 0 +-845 -515 746 0 +485 200 -915 0 +-801 835 78 0 +-360 517 -530 0 +-415 40 -545 0 +207 29 619 0 +363 -565 -557 0 +-32 346 24 0 +617 428 -446 0 +594 995 -564 0 +-123 -588 884 0 +-18 -801 -373 0 +-962 814 -526 0 +-289 605 -48 0 +222 -971 578 0 +-867 -551 -856 0 +-6 646 -445 0 +-485 -777 -480 0 +-573 -73 975 0 +-874 -126 -354 0 +-57 -559 501 0 +-188 -304 626 0 +-948 -474 383 0 +-496 -275 213 0 +616 606 -88 0 +228 612 240 0 +268 -482 -502 0 +-461 -403 -41 0 +-170 401 -841 0 +279 -579 435 0 +893 934 -311 0 +931 349 -484 0 +534 -247 308 0 +265 703 -585 0 +198 -570 166 0 +166 483 551 0 +-169 -542 -89 0 +-726 352 754 0 +-991 -951 -768 0 +-571 -133 -810 0 +-588 -976 -62 0 +-388 -840 935 0 +-211 799 -640 0 +-793 -63 -831 0 +682 180 637 0 +675 229 -364 0 +847 -572 -703 0 +800 -760 -56 0 +816 98 -78 0 +696 -679 547 0 +-715 987 -482 0 +-247 242 -972 0 +410 186 -174 0 +-194 61 -325 0 +859 787 836 0 +847 -39 -557 0 +-685 -148 -504 0 +-934 44 54 0 +904 -978 -186 0 +704 24 -276 0 +-59 113 -148 0 +384 491 -896 0 +-708 314 124 0 +220 -277 -229 0 +-74 -607 185 0 +211 -330 954 0 +427 201 562 0 +827 205 -253 0 +495 485 218 0 +-460 999 327 0 +-530 -958 -662 0 +-78 -234 -109 0 +185 -177 236 0 +675 893 -507 0 +-528 -915 510 0 +-972 111 -566 0 +915 -156 528 0 +901 -453 -489 0 +919 -91 -859 0 +-69 255 986 0 +-232 -33 286 0 +859 -99 -11 0 +-291 425 664 0 +-793 588 89 0 +615 -410 -521 0 +-953 -531 817 0 +537 168 -747 0 +808 123 -521 0 +-878 -978 779 0 +465 -986 -861 0 +295 872 -593 0 +190 159 147 0 +-441 -341 986 0 +144 -729 60 0 +559 877 -491 0 +29 -339 434 0 +-85 -297 140 0 +195 -6 115 0 +368 -609 -504 0 +-894 -749 623 0 +102 -366 743 0 +-823 -31 -567 0 +654 84 -148 0 +-130 116 -306 0 +728 -91 -281 0 +-628 -536 81 0 +269 901 920 0 +-695 -65 49 0 +-66 919 -884 0 +-508 88 -847 0 +-607 289 -682 0 +94 657 -131 0 +283 -508 841 0 +70 -479 -492 0 +227 574 -600 0 +690 708 515 0 +-853 -269 575 0 +-615 -717 18 0 +-139 166 -483 0 +720 746 976 0 +-328 320 -370 0 +985 709 637 0 +-499 -494 -589 0 +275 733 -469 0 +-666 877 -96 0 +644 362 653 0 +956 -27 -73 0 +-855 -834 -797 0 +-529 -922 -879 0 +-43 -573 404 0 +840 802 -831 0 +-42 -662 -303 0 +997 -340 -489 0 +-610 323 -901 0 +238 310 44 0 +-507 802 252 0 +839 84 870 0 +-676 -173 -606 0 +720 249 -358 0 +-796 422 139 0 +223 -946 246 0 +513 -700 -506 0 +560 -310 -147 0 +670 520 -652 0 +-146 -910 922 0 +333 -969 -164 0 +936 -814 585 0 +106 -135 979 0 +-48 191 544 0 +-667 -46 916 0 +551 -241 -269 0 +152 -493 231 0 +271 987 523 0 +-584 -751 444 0 +68 -488 661 0 +-490 -774 801 0 +-388 769 -394 0 +-319 -163 -936 0 +213 -978 410 0 +-856 339 -24 0 +590 -526 779 0 +753 -150 376 0 +866 253 -675 0 +-949 -892 -976 0 +260 -174 240 0 +339 351 -198 0 +-944 27 -773 0 +769 557 -149 0 +541 808 -100 0 +-847 601 -406 0 +-248 -786 546 0 +-596 -551 741 0 +537 -593 -253 0 +774 -333 -240 0 +-85 -244 696 0 +-190 -135 -392 0 +-916 141 721 0 +25 223 -354 0 +-966 -976 514 0 +572 -756 697 0 +370 98 -446 0 +585 -812 289 0 +775 -613 -943 0 +-171 -332 600 0 +-127 784 755 0 +-904 498 261 0 +-915 -462 961 0 +-733 -574 880 0 +-1000 -769 804 0 +-723 581 60 0 +-482 911 -884 0 +295 290 -271 0 +1 670 -304 0 +-13 452 772 0 +589 -963 -263 0 +781 132 87 0 +240 902 716 0 +464 636 564 0 +-853 179 297 0 +-359 -811 709 0 +-215 872 -534 0 +921 974 -653 0 +785 -964 -728 0 +108 741 307 0 +-890 21 -654 0 +-177 -236 686 0 +707 716 -998 0 +671 -791 936 0 +172 678 -967 0 +193 -742 800 0 +425 -880 780 0 +114 798 215 0 +964 954 -972 0 +-101 -320 -32 0 +583 812 -424 0 +973 607 -588 0 +-675 949 -544 0 +580 -790 -145 0 +-535 346 -911 0 +-334 388 -809 0 +-634 -25 -39 0 +-209 -148 520 0 +246 767 -669 0 +813 256 -148 0 +712 764 -19 0 +-755 -21 42 0 +-668 518 -187 0 +-711 954 -504 0 +768 753 -260 0 +-811 810 -824 0 +-225 941 -860 0 +751 -969 453 0 +-995 409 592 0 +-85 -582 791 0 +-681 -135 727 0 +-444 715 -286 0 +-303 199 373 0 +628 -966 -433 0 +-140 -186 967 0 +-930 758 850 0 +267 954 73 0 +-467 847 -272 0 +-466 -399 -104 0 +-906 459 -156 0 +465 -685 -412 0 +756 -482 795 0 +-661 -852 -464 0 +5 -615 116 0 +507 -752 607 0 +-184 298 -100 0 +305 104 424 0 +810 -771 -769 0 +-707 328 -936 0 +-506 -707 -899 0 +160 910 -833 0 +492 282 301 0 +633 211 -157 0 +256 231 -575 0 +-652 -794 881 0 +-874 963 880 0 +745 -136 -460 0 +-537 230 88 0 +-576 103 -42 0 +586 280 -862 0 +925 -5 863 0 +814 -567 72 0 +-852 -41 765 0 +410 419 -93 0 +985 654 -377 0 +-355 -171 750 0 +731 673 -576 0 +-240 633 -157 0 +578 959 936 0 +-981 675 -205 0 +690 -393 452 0 +603 -909 251 0 +222 -875 -689 0 +-597 -837 -124 0 +859 -345 -683 0 +123 -938 -452 0 +905 375 -465 0 +-947 -927 672 0 +369 33 -648 0 +-861 -530 -346 0 +740 290 845 0 +-94 559 589 0 +-753 301 -57 0 +-70 -486 -537 0 +-913 -607 -76 0 +703 -826 -202 0 +-192 303 -663 0 +-749 194 274 0 +889 -733 89 0 +-978 551 999 0 +344 -655 251 0 +-288 718 -470 0 +-411 687 36 0 +864 -890 252 0 +497 -431 -15 0 +-620 79 -411 0 +-972 -337 -712 0 +-645 923 -372 0 +-878 -545 747 0 +683 -211 -38 0 +-437 764 -30 0 +413 -40 -740 0 +-526 -392 -574 0 +-330 982 323 0 +649 587 200 0 +232 -586 -256 0 +-324 215 -510 0 +7 249 83 0 +933 767 252 0 +-481 670 -457 0 +-894 322 68 0 +473 -832 552 0 +555 -295 100 0 +-684 946 397 0 +383 417 381 0 +-755 759 634 0 +5 674 -708 0 +154 684 -647 0 +-501 -219 844 0 +-944 154 -949 0 +-353 411 633 0 +561 573 -430 0 +445 -773 -111 0 +445 436 -786 0 +-617 385 -609 0 +50 820 -763 0 +797 -553 -104 0 +719 -557 900 0 +-896 299 -738 0 +-751 232 947 0 +181 -189 -607 0 +768 293 -818 0 +955 -35 -687 0 +28 298 310 0 +688 -761 -269 0 +-937 459 -143 0 +834 807 -11 0 +-601 61 300 0 +-642 -137 -562 0 +-653 -78 536 0 +423 -435 -68 0 +-205 -367 623 0 +-615 -260 266 0 +-280 -685 955 0 +-341 539 504 0 +137 850 538 0 +767 -488 670 0 +-454 -607 457 0 +-75 107 928 0 +-4 324 -894 0 +-817 -272 113 0 +-673 -186 149 0 +-732 -393 -472 0 +865 -102 -551 0 +345 -404 -846 0 +-427 -468 -857 0 +188 466 -698 0 +805 -470 939 0 +-559 -565 42 0 +466 -208 756 0 +795 465 -367 0 +495 -787 -281 0 +-126 921 -222 0 +271 -980 192 0 +823 -767 974 0 +577 827 -822 0 +716 -614 694 0 +472 774 883 0 +-653 -74 -847 0 +376 -448 382 0 +369 689 973 0 +416 880 -869 0 +937 810 -967 0 +677 560 -627 0 +717 994 173 0 +-784 -392 -422 0 +-965 6 -545 0 +-870 1000 296 0 +950 -356 -171 0 +674 380 48 0 +-953 276 377 0 +984 -642 24 0 +-225 968 -25 0 +6 -995 99 0 +-861 686 -907 0 +578 19 74 0 +-307 474 -768 0 +74 109 -774 0 +900 -545 129 0 +754 -403 609 0 +966 -327 -186 0 +314 310 -382 0 +632 622 -227 0 +999 -254 -470 0 +561 481 -768 0 +350 -108 603 0 +-248 742 -527 0 +-368 131 837 0 +-633 479 19 0 +-597 -32 166 0 +-384 349 -253 0 +-211 618 -734 0 +319 591 997 0 +211 60 -687 0 +293 -689 475 0 +-18 -636 -315 0 +-880 -109 -332 0 +256 -172 -82 0 +-591 -788 371 0 +-997 689 960 0 +-624 -428 936 0 +665 181 -385 0 +1 -898 -886 0 +-377 -577 379 0 +-729 235 954 0 +921 173 -635 0 +904 -544 -112 0 +-919 660 875 0 +-548 180 -442 0 +598 -386 -331 0 +176 -843 -339 0 +943 -944 -273 0 +431 -671 -948 0 +-97 841 -688 0 +-10 78 600 0 +714 -595 867 0 +592 -431 -990 0 +-110 672 -765 0 +-70 -33 -508 0 +733 -730 661 0 +-585 -861 763 0 +-363 319 -553 0 +252 -536 209 0 +-656 641 412 0 +453 773 -200 0 +647 541 24 0 +-784 -536 -948 0 +-247 381 -260 0 +800 -626 -405 0 +-204 -1000 639 0 +-241 -799 -536 0 +387 223 2 0 +-930 -129 -441 0 +116 -829 -637 0 +668 -975 977 0 +-636 387 -948 0 +741 188 -410 0 +-106 934 -17 0 +240 675 629 0 +970 68 332 0 +627 -6 -591 0 +374 68 399 0 +-357 853 373 0 +-616 -114 358 0 +701 78 910 0 +-121 679 115 0 +594 -640 81 0 +68 871 981 0 +-34 -765 -800 0 +-503 -582 651 0 +922 -839 -501 0 +-236 757 661 0 +-3 -883 640 0 +174 389 -61 0 +-1 -110 -705 0 +-246 663 -25 0 +485 -968 -47 0 +413 794 80 0 +-339 60 -379 0 +-760 942 -748 0 +782 744 -414 0 +409 747 -691 0 +126 411 -619 0 +-715 -431 -597 0 +-922 -147 -145 0 +-826 252 -996 0 +-651 -296 263 0 +-796 291 882 0 +-790 472 -61 0 +412 -31 -59 0 +523 611 -211 0 +942 -917 -613 0 +-613 -147 -587 0 +-481 -359 -822 0 +769 -26 854 0 +504 -566 -930 0 +728 -211 -559 0 +-331 -84 9 0 +456 872 -158 0 +774 668 272 0 +107 -142 786 0 +85 217 -278 0 +-460 -282 -945 0 +751 -46 -981 0 +-729 522 -433 0 +496 -177 -85 0 +541 -430 -543 0 +987 364 -929 0 +-417 -124 -659 0 +935 13 302 0 +65 -707 117 0 +401 -112 -351 0 +-610 940 366 0 +302 544 -928 0 +898 -417 732 0 +-966 391 124 0 +24 -114 -470 0 +374 -799 741 0 +-160 915 423 0 +-26 -124 132 0 +-239 408 161 0 +-350 88 -389 0 +602 466 261 0 +471 -180 505 0 +881 178 -345 0 +-474 811 77 0 +-366 -62 565 0 +-113 -43 519 0 +-688 380 -435 0 +227 -439 -73 0 +-293 -774 -343 0 +-354 -781 143 0 +-211 510 859 0 +-55 80 -499 0 +-738 -522 -849 0 +-964 -206 761 0 +126 39 -906 0 +863 759 -292 0 +30 -449 995 0 +-768 860 175 0 +-658 -86 -26 0 +762 532 -639 0 +-216 386 554 0 +-443 306 -756 0 +754 747 838 0 +569 -115 340 0 +925 -725 971 0 +-645 665 -603 0 +-421 687 -982 0 +797 508 -485 0 +84 207 -828 0 +409 -943 -432 0 +-920 30 -226 0 +-630 -939 -127 0 +-246 340 -711 0 +-948 366 200 0 +-542 -828 441 0 +-513 -759 78 0 +404 289 -81 0 +-868 -88 803 0 +4 376 -888 0 +273 -31 596 0 +-760 -468 168 0 +-783 98 431 0 +933 159 705 0 +560 334 -437 0 +-60 418 875 0 +-641 267 -419 0 +-456 -280 -201 0 +-229 205 587 0 +695 644 93 0 +-467 14 -714 0 +704 805 883 0 +-113 498 -355 0 +-703 12 -262 0 +-242 -604 -649 0 +702 251 -244 0 +518 640 328 0 +398 -137 476 0 +-374 -504 -709 0 +-898 -186 289 0 +39 752 147 0 +685 53 601 0 +-73 -547 881 0 +-662 808 -52 0 +-232 -493 278 0 +-146 649 -461 0 +-226 776 931 0 +-881 -463 206 0 +728 605 -331 0 +-9 -600 619 0 +815 -592 -730 0 +930 -693 -877 0 +-314 -961 807 0 +-398 316 -733 0 +-897 -81 -539 0 +254 -948 -383 0 +170 -379 -793 0 +183 624 -652 0 +937 686 98 0 +-106 -976 330 0 +-602 1 -127 0 +-22 271 751 0 +87 -466 515 0 +-665 -216 238 0 +970 -802 576 0 +-418 243 968 0 +4 -622 -510 0 +954 -44 -547 0 +-681 -552 579 0 +-495 -525 6 0 +-546 -466 860 0 +883 722 115 0 +-914 558 575 0 +-255 -156 647 0 +-640 -228 -114 0 +747 352 297 0 +354 -627 179 0 +-44 -908 850 0 +-745 838 -243 0 +676 998 893 0 +748 -514 98 0 +-890 -175 -589 0 +111 -873 7 0 +124 803 748 0 +48 -711 139 0 +-641 576 233 0 +-553 163 598 0 +327 -192 -299 0 +-588 -306 796 0 +-341 -926 688 0 +73 -569 -955 0 +320 -958 74 0 +411 2 -210 0 +159 582 -51 0 +-510 163 -378 0 +-935 42 -513 0 +-973 -651 952 0 +-886 -276 884 0 +-343 -295 434 0 +-66 521 -888 0 +90 -599 -176 0 +797 257 68 0 +938 -108 -129 0 +-476 282 231 0 +887 273 -480 0 +-437 674 162 0 +735 911 -334 0 +-543 -316 -422 0 +747 335 39 0 +-599 -236 567 0 +692 499 -589 0 +780 -393 970 0 +879 -318 -633 0 +756 446 541 0 +-84 -770 -606 0 +954 266 934 0 +-316 243 -584 0 +-359 311 817 0 +-807 648 -685 0 +-1 -224 915 0 +-485 -309 346 0 +-961 110 122 0 +371 173 147 0 +-956 -757 -321 0 +749 104 -467 0 +-344 709 765 0 +-521 -278 -297 0 +635 -354 183 0 +678 920 -955 0 +82 -883 -672 0 +643 -38 274 0 +15 -871 -427 0 +-276 607 357 0 +477 -728 394 0 +-910 -84 163 0 +136 908 758 0 +-934 -493 533 0 +70 -290 424 0 +740 -4 960 0 +178 -775 -770 0 +135 598 62 0 +319 38 955 0 +-566 -907 -781 0 +569 99 470 0 +15 -610 977 0 +538 221 119 0 +-227 -477 860 0 +-479 136 -786 0 +305 564 -772 0 +504 -593 63 0 +66 -34 601 0 +423 -576 -305 0 +64 -265 -969 0 +-118 143 369 0 +-486 824 -261 0 +-39 -363 -809 0 +996 -197 -297 0 +-328 -401 -782 0 +-28 -581 806 0 +-397 -474 953 0 +-45 -661 172 0 +870 -213 683 0 +298 -69 492 0 +838 511 -360 0 +-400 514 195 0 +782 884 638 0 +-421 -192 -789 0 +-277 -472 -384 0 +-191 -579 73 0 +-944 -585 -897 0 +1 301 143 0 +404 -815 -342 0 +-136 -857 -183 0 +576 22 -773 0 +-877 548 654 0 +578 -600 93 0 +513 -128 353 0 +688 -325 -652 0 +-631 512 71 0 +74 -15 -638 0 +748 -597 356 0 +-344 366 -575 0 +-153 -835 -117 0 +-274 -332 -997 0 +-835 333 -36 0 +-217 -320 40 0 +-91 240 435 0 +-796 -311 851 0 +506 538 -915 0 +150 -318 -895 0 +-251 -818 631 0 +552 628 63 0 +713 -447 -535 0 +184 -786 386 0 +-458 -422 573 0 +327 191 5 0 +289 291 220 0 +62 222 -208 0 +-463 -970 -52 0 +336 727 612 0 +-753 -464 -596 0 +379 -948 321 0 +593 -880 -698 0 +-366 331 -328 0 +-351 -235 193 0 +871 671 -663 0 +-544 479 147 0 +323 406 -21 0 +172 46 262 0 +-500 -138 715 0 +966 776 491 0 +149 6 338 0 +-477 500 -650 0 +-243 850 580 0 +-768 -76 -232 0 +376 -438 912 0 +310 -674 -3 0 +940 -474 -645 0 +46 -866 142 0 +373 969 -495 0 +-358 801 -758 0 +736 -496 -20 0 +-580 1 479 0 +133 658 -577 0 +899 -580 -558 0 +607 -427 850 0 +991 82 764 0 +14 -514 -434 0 +848 -553 -385 0 +73 791 -509 0 +-277 23 799 0 +821 -961 538 0 +676 -5 706 0 +-864 -257 -941 0 +-124 32 -150 0 +-490 576 -171 0 +-44 -835 -257 0 +-715 -706 341 0 +992 -752 -70 0 +56 -435 -217 0 +348 298 -680 0 +604 325 -30 0 +-529 -881 564 0 +-971 -548 -233 0 +800 -382 -224 0 +343 -173 -587 0 +-189 -368 -319 0 +-901 975 -494 0 +728 627 768 0 +533 224 941 0 +738 240 -871 0 +473 589 -39 0 +-569 -185 706 0 +-817 342 358 0 +145 -956 -549 0 +306 -69 -485 0 +550 842 929 0 +-698 113 -9 0 +-143 -884 -488 0 +-891 -474 -907 0 +-62 -451 793 0 +-836 730 896 0 +382 -755 936 0 +83 366 712 0 +-765 874 -679 0 +840 -541 -382 0 +-784 297 -334 0 +-444 -144 -705 0 +-372 -821 -798 0 +102 -292 577 0 +524 -49 225 0 +-699 -225 420 0 +780 -221 807 0 +832 959 -951 0 +-443 146 -998 0 +-336 312 -425 0 +-724 -2 -490 0 +488 -472 632 0 +606 997 -474 0 +989 -725 163 0 +-30 -484 365 0 +914 -465 908 0 +-896 378 -151 0 +-901 599 23 0 +193 -643 915 0 +738 168 322 0 +-599 -231 -477 0 +599 -163 985 0 +-645 829 713 0 +-751 596 80 0 +147 -171 69 0 +990 737 -961 0 +84 111 951 0 +944 -679 -910 0 +245 371 -771 0 +-337 62 -461 0 +272 -47 -326 0 +418 189 927 0 +867 810 -657 0 +835 856 -649 0 +-628 -360 658 0 +-139 -351 490 0 +177 -373 287 0 +847 -448 98 0 +-108 488 544 0 +-23 578 476 0 +178 -683 611 0 +-656 -309 285 0 +938 -913 632 0 +606 700 -649 0 +27 421 -624 0 +201 -587 822 0 +697 111 -844 0 +-276 -355 -736 0 +953 278 -606 0 +518 609 173 0 +-795 -86 35 0 +212 -146 398 0 +-811 375 -854 0 +-770 807 346 0 +435 983 -403 0 +73 300 94 0 +940 -879 134 0 +78 -307 136 0 +-507 110 -600 0 +655 -264 987 0 +265 150 -29 0 +348 724 -635 0 +238 339 343 0 +-591 91 -949 0 +186 -313 -771 0 +-571 825 -160 0 +-363 -721 -627 0 +-488 726 16 0 +482 -958 976 0 +-407 150 963 0 +835 76 884 0 +456 -354 241 0 +-46 458 561 0 +-772 426 -802 0 +-814 110 -232 0 +8 708 794 0 +-341 -581 66 0 +385 946 77 0 +-294 628 -495 0 +439 131 -593 0 +379 570 -337 0 +-967 -353 137 0 +693 -923 -958 0 +-475 -278 274 0 +856 -308 -527 0 +-204 918 -326 0 +503 328 859 0 +679 -667 -502 0 +-521 415 -495 0 +-968 299 -45 0 +-80 699 349 0 +359 -621 -602 0 +962 136 -982 0 +-868 15 758 0 +-742 -91 -717 0 +-469 733 436 0 +-308 -672 79 0 +-815 605 379 0 +-687 -600 -855 0 +658 -634 517 0 +-419 -624 -216 0 +520 620 -297 0 +502 664 -672 0 +174 -194 -347 0 +642 285 409 0 +-626 856 698 0 +-819 -994 431 0 +624 -349 -308 0 +350 -876 540 0 +126 424 -893 0 +-560 -376 -543 0 +-97 -390 -875 0 +439 -925 -413 0 +-357 -516 832 0 +599 -609 -768 0 +-698 -340 -765 0 +108 421 -964 0 +-856 -7 964 0 +65 -504 -85 0 +694 -57 -224 0 +73 -62 -288 0 +326 946 785 0 +36 853 169 0 +-574 156 538 0 +127 -374 -935 0 +375 -5 -761 0 +817 583 -403 0 +-178 -316 -825 0 +-193 -751 293 0 +526 -522 848 0 +91 -354 -53 0 +363 -168 680 0 +-721 -229 -418 0 +-927 -319 -653 0 +-410 -710 546 0 +391 644 967 0 +-636 -50 225 0 +-445 -635 631 0 +-26 701 340 0 +83 -96 868 0 +-607 -522 865 0 +-620 -519 62 0 +-199 750 -54 0 +959 -533 -492 0 +51 665 -784 0 +209 -654 137 0 +574 -262 622 0 +-41 -567 -415 0 +319 708 -563 0 +-441 -146 -569 0 +-166 354 -661 0 +606 -382 -255 0 +756 -122 109 0 +-354 -577 399 0 +-225 212 -289 0 +761 951 703 0 +-132 828 -690 0 +-389 501 -185 0 +-573 -462 78 0 +272 511 -42 0 +810 358 467 0 +-389 -286 678 0 +-44 -391 -415 0 +987 825 807 0 +73 204 -589 0 +532 937 -434 0 +637 797 410 0 +-227 -840 -889 0 +760 437 839 0 +644 -221 325 0 +-790 -670 -961 0 +-353 -999 445 0 +-625 -135 -52 0 +416 -709 -393 0 +-642 545 -875 0 +-49 -303 297 0 +201 -597 204 0 +420 -150 995 0 +-265 -519 -853 0 +-889 401 737 0 +779 679 186 0 +583 88 -299 0 +561 252 958 0 +884 -23 570 0 +210 -20 266 0 +706 263 -912 0 +-937 648 -521 0 +-601 -176 672 0 +-455 -640 138 0 +-904 -721 -259 0 +-70 -612 872 0 +-678 635 215 0 +-768 526 707 0 +-690 -494 -752 0 +360 625 572 0 +154 -66 512 0 +929 738 -286 0 +963 698 177 0 +449 -713 -212 0 +-292 -539 551 0 +-841 -688 -122 0 +452 817 -256 0 +-426 -312 -263 0 +-463 407 561 0 +-968 373 147 0 +765 -359 303 0 +420 -51 -862 0 +-815 676 237 0 +572 470 -540 0 +-927 -889 -547 0 +-111 -116 649 0 +-981 -546 463 0 +-513 -146 400 0 +708 -102 461 0 +-140 1000 789 0 +-724 615 576 0 +635 -197 -291 0 +263 658 590 0 +182 -966 -289 0 +-865 -74 -447 0 +705 327 -531 0 +954 540 -56 0 +-839 38 -857 0 +-218 -691 736 0 +-660 639 816 0 +-63 -637 519 0 +-49 -819 -336 0 +989 -803 -838 0 +-365 -438 -203 0 +24 -494 -430 0 +791 -550 493 0 +-666 -793 100 0 +-725 -139 -253 0 +-787 -9 -191 0 +-208 -322 -895 0 +997 -371 491 0 +-443 599 -220 0 +-386 -969 -731 0 +261 -648 878 0 +834 -158 730 0 +998 392 276 0 +-939 472 -427 0 +-310 -797 618 0 +881 -785 485 0 +-95 -854 382 0 +541 956 -737 0 +-826 983 -163 0 +-232 -310 306 0 +-149 -355 -706 0 +884 -86 475 0 +-126 782 -631 0 +952 -730 934 0 +-760 -1000 971 0 +-710 125 472 0 +650 948 -457 0 +830 94 -201 0 +429 772 839 0 +-401 953 -25 0 +-402 847 -905 0 +407 -420 235 0 +239 705 519 0 +339 -963 545 0 +-811 -300 -151 0 +163 -913 -107 0 +-46 248 726 0 +982 630 -612 0 +577 381 417 0 +-686 -780 -642 0 +-395 -28 -330 0 +-67 986 -427 0 +717 999 -363 0 +-174 -878 843 0 +376 829 795 0 +779 -322 129 0 +-42 70 752 0 +-33 850 358 0 +690 -527 -923 0 +-761 867 328 0 +-927 117 554 0 +159 -997 -427 0 +316 509 854 0 +373 124 -442 0 +-856 852 -708 0 +638 -720 899 0 +-434 861 -912 0 +824 -402 -795 0 +817 215 704 0 +441 13 439 0 +83 687 -714 0 +-791 -70 69 0 +412 -728 931 0 +-240 122 -961 0 +378 220 450 0 +493 612 228 0 +-189 521 912 0 +-772 536 -436 0 +-380 -578 -859 0 +905 305 -489 0 +430 48 -1000 0 +920 294 -312 0 +-670 -797 47 0 +-423 -86 -169 0 +958 -531 817 0 +-163 -743 -855 0 +-225 956 -769 0 +-852 912 282 0 +952 -276 -978 0 +173 -618 706 0 +769 -823 555 0 +375 -740 577 0 +889 -306 585 0 +-415 258 -163 0 +-121 337 -428 0 +-745 -16 259 0 +192 556 -850 0 +772 617 -606 0 +-598 -260 -180 0 +741 -108 -988 0 +-363 3 967 0 +-590 -941 587 0 +506 -391 817 0 +-102 183 -368 0 +-341 -790 -772 0 +-965 -65 902 0 +245 429 -940 0 +613 365 186 0 +-933 718 -175 0 +615 636 -111 0 +-763 -138 -578 0 +903 -851 -319 0 +196 -702 -289 0 +787 -988 455 0 +688 426 603 0 +206 46 -204 0 +-530 -986 994 0 +979 875 -79 0 +-603 557 -25 0 +62 -358 -811 0 +-231 -96 -457 0 +-72 599 779 0 +300 489 -200 0 +-804 936 433 0 +923 738 -565 0 +919 -879 -563 0 +269 -967 -747 0 +-318 669 -546 0 +-226 173 369 0 +-844 -550 433 0 +809 -514 -354 0 +-911 -932 -844 0 +814 -481 -628 0 +813 497 -61 0 +650 326 -206 0 +478 506 -382 0 +-908 -341 457 0 +-713 -411 140 0 +-384 -276 -805 0 +689 232 -860 0 +727 -337 273 0 +121 534 25 0 +384 -403 -338 0 +-128 299 -615 0 +-363 -714 612 0 +63 -17 767 0 +-522 685 32 0 +-921 -256 -427 0 +393 -748 413 0 +17 -55 -792 0 +-483 559 116 0 +634 -489 453 0 +-458 5 968 0 +-94 246 946 0 +-919 -678 -509 0 +340 -181 513 0 +-668 234 570 0 +-913 521 -393 0 +831 -534 973 0 +928 202 -522 0 +-740 -429 535 0 +-454 118 -895 0 +-91 -402 993 0 +-806 763 994 0 +573 710 -133 0 +258 -455 -9 0 +-481 897 287 0 +692 -650 378 0 +6 103 -151 0 +4 -176 -80 0 +111 -787 -248 0 +-946 782 -954 0 +917 772 165 0 +308 833 224 0 +-439 -156 791 0 +284 -613 912 0 +832 443 -240 0 +945 859 171 0 +284 -326 590 0 +-21 76 193 0 +-659 -315 942 0 +-121 -923 502 0 +-913 328 -578 0 +-149 563 561 0 +-299 -866 -673 0 +-44 528 -576 0 +-385 545 -813 0 +-249 625 694 0 +909 -328 571 0 +-240 237 -86 0 +-624 -164 -449 0 +-687 -494 -319 0 +209 -664 950 0 +997 828 972 0 +-350 -213 -488 0 +-15 -558 85 0 +-717 842 532 0 +-944 -265 -932 0 +-123 -880 211 0 +-530 -857 702 0 +373 548 -883 0 +-773 -930 992 0 +809 -788 -786 0 +996 911 454 0 +129 525 265 0 +-101 -983 -856 0 +550 -806 286 0 +417 -828 -999 0 +551 70 -194 0 +12 -896 191 0 +-935 882 -963 0 +986 -487 -733 0 +319 -1000 -384 0 +140 -920 -703 0 +-347 -10 594 0 +482 -645 906 0 +-982 951 295 0 +926 -499 846 0 +732 -215 -797 0 +923 81 752 0 +-696 791 -978 0 +-130 -636 -666 0 +-298 46 142 0 +-946 -318 -332 0 +520 753 402 0 +242 745 796 0 +-124 878 631 0 +366 312 840 0 +-76 -254 -113 0 +-680 808 565 0 +-721 223 339 0 +939 868 -149 0 +964 31 644 0 +-340 768 -291 0 +246 366 -473 0 +804 182 283 0 +348 56 941 0 +-239 71 104 0 +-365 443 -959 0 +-924 -314 986 0 +-939 -157 -148 0 +48 -344 421 0 +-133 -914 -356 0 +706 -302 200 0 +-261 599 -761 0 +-606 -111 -207 0 +232 661 113 0 +-995 -997 180 0 +179 353 450 0 +39 -343 -540 0 +949 -360 -824 0 +149 -588 -961 0 +-620 -739 -915 0 +376 -801 -152 0 +-301 -278 300 0 +778 -966 -504 0 +947 -915 -325 0 +293 -453 280 0 +-184 -94 507 0 +-920 -360 73 0 +-500 -578 589 0 +-257 -315 835 0 +-396 -501 618 0 +-217 -692 -232 0 +-305 741 522 0 +611 635 -340 0 +336 -199 -739 0 +-61 -218 243 0 +-419 -745 723 0 +-68 846 -67 0 +222 -634 -479 0 +-220 -483 -586 0 +964 -126 368 0 +-927 297 -964 0 +-843 955 708 0 +-100 -895 -734 0 +271 -62 -404 0 +346 111 65 0 +419 -192 781 0 +-952 -404 209 0 +-850 -18 -277 0 +164 -419 671 0 +958 -292 800 0 +636 289 362 0 +-122 -28 837 0 +480 396 954 0 +-888 -508 381 0 +-910 -715 559 0 +-422 104 -331 0 +-736 586 679 0 +-362 733 -34 0 +-330 953 967 0 +127 -215 296 0 +-415 675 -809 0 +-606 753 -599 0 +156 946 70 0 +-355 -73 396 0 +-32 -99 177 0 +100 862 729 0 +-648 -45 125 0 +675 -543 -80 0 +396 669 -338 0 +-370 -607 -89 0 +792 106 -925 0 +352 -396 -430 0 +-129 957 -290 0 +358 -218 54 0 +-917 -995 -668 0 +-221 -140 -347 0 +-334 -722 890 0 +-458 -893 230 0 +-209 987 -175 0 +928 -993 -96 0 +-208 976 -410 0 +576 966 252 0 +-157 460 -914 0 +306 -965 -122 0 +463 -425 -954 0 +105 557 243 0 +270 -914 -517 0 +-352 -579 979 0 +35 -679 -855 0 +-610 51 154 0 +546 -137 -612 0 +396 913 -605 0 +-489 -262 535 0 +51 -959 209 0 +-719 292 764 0 +-759 566 365 0 +-401 331 -118 0 +237 -622 -192 0 +790 447 987 0 +842 -290 857 0 +267 -970 -207 0 +830 -688 215 0 +549 -540 402 0 +-303 -427 446 0 +-987 -655 176 0 +521 -709 806 0 +-602 -805 -178 0 +-743 960 -580 0 +-524 -29 -353 0 +-187 -190 663 0 +-485 -180 5 0 +-380 -1 -871 0 +-186 -405 92 0 +242 -736 832 0 +860 915 -598 0 +64 62 -667 0 +-292 47 -409 0 +362 612 -935 0 +69 -448 882 0 +-291 784 -539 0 +979 -641 407 0 +97 342 769 0 +-366 38 174 0 +-596 -509 777 0 +130 892 261 0 +314 75 -524 0 +256 795 510 0 +380 864 771 0 +-672 -361 -477 0 +776 -219 595 0 +-861 898 234 0 +-371 -187 300 0 +635 -76 156 0 +828 518 490 0 +825 846 -614 0 +453 6 482 0 +-334 -33 -309 0 +-28 546 -757 0 +485 -274 95 0 +-363 -548 877 0 +879 -82 -689 0 +-723 100 674 0 +418 76 -706 0 +908 9 962 0 +-23 510 843 0 +-193 860 171 0 +935 -4 127 0 +350 103 131 0 +464 -459 -515 0 +51 776 734 0 +-448 -342 642 0 +614 -24 694 0 +-51 -721 -994 0 +538 -600 -611 0 +916 88 -287 0 +-488 -939 153 0 +252 677 746 0 +263 71 616 0 +934 -920 -10 0 +605 -252 925 0 +-680 496 -880 0 +648 -640 -4 0 +567 100 -831 0 +196 -712 388 0 +-488 -18 497 0 +886 -267 -637 0 +-504 519 111 0 +-96 277 697 0 +146 -48 453 0 +-305 815 330 0 +-921 -142 715 0 +-110 -43 -948 0 +612 -922 13 0 +799 659 309 0 +-315 369 54 0 +-831 338 352 0 +-515 880 100 0 +-575 -675 -470 0 +-236 -283 -76 0 +-125 -112 -130 0 +431 935 116 0 +-34 953 451 0 +629 -713 640 0 +-96 379 -681 0 +200 402 99 0 +-953 -423 -386 0 +-166 637 -113 0 +563 314 -179 0 +877 264 -993 0 +-337 48 -743 0 +-362 -390 844 0 +-542 -374 -376 0 +305 -468 -939 0 +-801 541 726 0 +-239 802 716 0 +-381 418 -676 0 +593 -656 241 0 +418 -757 125 0 +-823 -485 -303 0 +-459 -747 -345 0 +846 -209 -709 0 +-739 565 655 0 +-945 484 -56 0 +-373 -659 211 0 +-165 -624 -153 0 +395 446 -267 0 +189 -32 137 0 +368 -597 -679 0 +415 270 -503 0 +37 -903 -68 0 +30 753 -203 0 +-760 -520 777 0 +728 196 445 0 +-180 695 823 0 +152 -284 140 0 +-898 409 -862 0 +849 69 -839 0 +225 694 -575 0 +210 45 -18 0 +-691 -297 76 0 +195 -820 -485 0 +-27 -741 -956 0 +-81 -514 -825 0 +831 -72 268 0 +-258 -723 -984 0 +476 351 414 0 +101 76 722 0 +-291 -866 -567 0 +411 268 98 0 +-988 599 -418 0 +991 366 -270 0 +141 478 -744 0 +-787 497 756 0 +535 -388 219 0 +-817 -815 250 0 +-690 544 -749 0 +-937 20 -404 0 +46 693 82 0 +584 -897 -847 0 +939 653 -335 0 +-189 -903 -400 0 +844 519 -652 0 +135 -257 491 0 +52 -312 103 0 +-642 -625 -800 0 +-724 -850 -785 0 +-547 279 -986 0 +-632 -600 -108 0 +62 -735 -204 0 +82 213 -231 0 +364 308 277 0 +-325 -534 504 0 +-755 872 760 0 +910 423 -639 0 +-702 854 -156 0 +213 655 232 0 +753 729 550 0 +-282 -98 232 0 +987 -999 5 0 +784 54 481 0 +947 844 599 0 +-112 1000 295 0 +-663 -235 190 0 +-354 700 -746 0 +233 245 517 0 +596 -415 987 0 +-117 -458 877 0 +228 788 703 0 +285 -9 661 0 +-370 -407 -539 0 +407 -324 92 0 +695 -246 260 0 +-573 -165 -544 0 +35 85 -240 0 +-549 -441 496 0 +-891 631 703 0 +-389 -548 368 0 +-385 -457 807 0 +-650 -691 708 0 +-877 -153 -832 0 +-209 958 292 0 +643 -153 -640 0 +710 45 300 0 +-603 171 -901 0 +401 -984 751 0 +540 372 724 0 +601 995 231 0 +605 -861 211 0 +-61 -89 660 0 +232 411 31 0 +-207 471 632 0 +-886 7 436 0 +248 -137 464 0 +616 -754 29 0 +-684 -645 807 0 +532 -668 -194 0 +477 -541 227 0 +-793 -670 -775 0 +-323 -675 637 0 +325 508 -612 0 +499 -71 -335 0 +482 67 677 0 +-87 905 492 0 +-616 -328 -228 0 +304 964 -228 0 +-308 -359 952 0 +845 -652 794 0 +161 -92 375 0 +670 -872 926 0 +686 6 -576 0 +-732 33 -630 0 +-151 -341 400 0 +937 -890 160 0 +-92 -971 -730 0 +207 -232 107 0 +-810 -597 -213 0 +312 246 -944 0 +503 -504 -473 0 +-448 654 -243 0 +267 367 819 0 +-441 765 270 0 +-582 -189 713 0 +-763 762 419 0 +530 678 -442 0 +-482 599 -495 0 +-469 -535 555 0 +-209 856 -11 0 +-370 569 -165 0 +9 307 654 0 +175 -718 51 0 +530 736 205 0 +-635 972 -848 0 +746 -419 -427 0 +571 -84 181 0 +-248 414 -298 0 +-240 293 664 0 +-196 657 -8 0 +328 -629 623 0 +777 -690 196 0 +155 -330 117 0 +-37 891 -40 0 +-630 222 -926 0 +-389 296 -48 0 +359 666 455 0 +-20 636 300 0 +-122 374 -427 0 +-918 90 -107 0 +217 958 984 0 +973 -656 -134 0 +-753 288 715 0 +206 903 435 0 +874 118 -447 0 +-882 146 -105 0 +-760 -635 -580 0 +-712 -733 140 0 +-50 919 788 0 +87 791 -16 0 +213 506 -42 0 +395 171 -898 0 +687 -829 -91 0 +-325 819 553 0 +-449 169 643 0 +799 -734 -270 0 +324 -305 372 0 +-757 -114 17 0 +71 -969 275 0 +490 544 136 0 +16 -774 745 0 +-578 -736 487 0 +210 -812 428 0 +-255 -412 -159 0 +114 -583 208 0 +778 290 985 0 +171 -466 -797 0 +-35 -254 124 0 +643 979 524 0 +-405 -922 979 0 +177 990 -54 0 +456 -733 371 0 +-369 280 786 0 +527 986 658 0 +173 -291 -613 0 +-176 471 726 0 +234 908 -576 0 +-597 -760 -33 0 +410 340 93 0 +898 457 622 0 +-158 -671 -308 0 +-786 714 -543 0 +-400 846 -507 0 +59 -497 74 0 +912 915 819 0 +464 -798 -938 0 +589 -222 -143 0 +-830 207 731 0 +-285 -472 -748 0 +88 65 125 0 +-948 -11 366 0 +-452 161 420 0 +-395 984 818 0 +619 -508 -358 0 +-644 -49 -923 0 +-273 580 176 0 +-463 540 -724 0 +-666 -337 340 0 +118 161 -282 0 +-506 796 -387 0 +-754 610 190 0 +-434 152 -468 0 +-329 -991 -760 0 +-682 324 -438 0 +-601 -3 -127 0 +-5 -453 254 0 +516 -597 -925 0 +-239 641 -486 0 +-14 795 -113 0 +-251 -145 -810 0 +817 426 854 0 +111 997 -370 0 +-243 -147 965 0 +106 -911 9 0 +-606 -628 623 0 +-6 -259 122 0 +105 -958 658 0 +932 416 24 0 +-158 -56 322 0 +968 -651 -185 0 +-186 -671 346 0 +749 911 717 0 +-816 -912 653 0 +38 221 663 0 +-379 59 313 0 +-164 -414 -295 0 +-34 638 -633 0 +-794 490 457 0 +102 -582 -728 0 +-490 -161 -927 0 +902 677 -322 0 +221 922 746 0 +-869 350 -304 0 +184 145 734 0 +641 192 624 0 +-305 -492 -430 0 +611 786 -841 0 +-13 -949 764 0 +-500 364 -783 0 +277 -155 736 0 +890 -48 603 0 +506 -371 504 0 +456 -452 371 0 +513 -427 -584 0 +198 -820 433 0 +809 -206 -373 0 +710 -731 505 0 +-120 481 656 0 +458 -999 -600 0 +347 610 -56 0 +-361 -753 139 0 +426 -982 641 0 +-820 802 -961 0 +957 701 340 0 +-84 -643 30 0 +963 -464 919 0 +301 -643 472 0 +-354 42 -297 0 +-705 -650 694 0 +-818 714 206 0 +-289 -397 -274 0 +70 711 -516 0 +538 739 -683 0 +-328 159 658 0 +979 12 80 0 +-702 -899 173 0 +-691 746 685 0 +649 720 -628 0 +329 -231 871 0 +884 -361 69 0 +-939 -112 -245 0 +-569 174 -214 0 +-792 833 -579 0 +-521 570 -469 0 +-761 510 808 0 +-32 -901 -894 0 +756 204 293 0 +-202 290 102 0 +-697 -638 -343 0 +874 -533 934 0 +576 -99 965 0 +419 206 -92 0 +111 -777 -827 0 +-936 323 716 0 +-155 -584 291 0 +46 -164 -438 0 +559 759 722 0 +628 -821 -569 0 +-360 -876 555 0 +279 -732 -432 0 +824 -579 348 0 +-363 -283 945 0 +101 423 -56 0 +588 855 -684 0 +757 257 214 0 +-488 29 -775 0 +316 -14 -667 0 +742 -832 954 0 +-591 -694 -859 0 +-147 986 -798 0 +640 -662 437 0 +-828 -462 871 0 +-991 430 153 0 +-719 -303 6 0 +343 73 495 0 +465 592 684 0 +-966 -931 411 0 +-945 355 -104 0 +-288 -771 -328 0 +-715 365 -656 0 +774 277 799 0 +-395 -697 33 0 +782 -426 -732 0 +-673 223 738 0 +-884 -130 -674 0 +408 568 -261 0 +-103 623 207 0 +-823 639 -546 0 +-576 700 -11 0 +-625 -51 440 0 +880 -754 14 0 +708 -743 -327 0 +-4 -371 -11 0 +266 314 -844 0 +897 988 934 0 +189 450 869 0 +420 -541 112 0 +599 288 36 0 +-319 -77 749 0 +-421 -906 -222 0 +-793 259 -141 0 +394 -660 -757 0 +-474 959 -24 0 +-543 950 302 0 +-589 538 299 0 +-297 638 250 0 +735 -584 320 0 +-747 -333 -809 0 +801 -705 942 0 +-341 -622 204 0 +73 832 -237 0 +-705 -53 -995 0 +607 -992 328 0 +401 -513 33 0 +803 483 197 0 +129 -281 387 0 +113 401 -110 0 +39 612 928 0 +348 -539 -9 0 +267 -663 -524 0 +-354 376 326 0 +-180 -451 754 0 +-952 -356 521 0 +-127 -645 36 0 +-312 -965 -697 0 +-975 633 159 0 +-770 -713 983 0 +-612 -105 198 0 +329 533 -860 0 +-91 487 -422 0 +560 -586 -206 0 +-104 -317 402 0 +-582 -94 976 0 +897 575 -211 0 +-640 -813 -992 0 +819 -792 297 0 +-312 -337 -194 0 +349 -692 -933 0 +320 459 -413 0 +911 278 787 0 +704 26 -160 0 +102 -923 -831 0 +776 -930 -623 0 +241 -280 -991 0 +158 722 -270 0 +750 -936 707 0 +916 661 334 0 +-441 770 598 0 +418 -677 888 0 +-944 44 621 0 +820 278 -862 0 +-712 -824 272 0 +209 -375 -400 0 +-715 -788 -82 0 +339 706 239 0 +475 -822 428 0 +-341 -132 215 0 +174 39 604 0 +308 400 -774 0 +719 -862 579 0 +-172 -505 -856 0 +-540 -589 -672 0 +-925 816 684 0 +-52 61 -398 0 +363 -177 735 0 +-763 383 -917 0 +-401 830 -359 0 +-779 114 -643 0 +54 138 902 0 +327 -576 -717 0 +418 635 729 0 +-506 773 -711 0 +-950 213 -814 0 +-103 -7 -225 0 +220 -309 539 0 +-925 59 -757 0 +454 986 591 0 +599 -124 -971 0 +730 -721 -825 0 +128 -84 -157 0 +615 602 57 0 +-132 -658 681 0 +-209 -782 354 0 +805 -540 110 0 +596 -230 -939 0 +-513 -169 -183 0 +-184 848 619 0 +-898 -794 -215 0 +16 613 -370 0 +291 -861 990 0 +409 118 318 0 +863 -839 378 0 +-236 -642 -770 0 +-958 300 451 0 +137 -364 465 0 +-169 -728 -981 0 +-320 77 -645 0 +361 -982 674 0 +315 -29 600 0 +685 -645 563 0 +-5 751 8 0 +-287 -979 -119 0 +-532 692 -113 0 +-192 -772 435 0 +44 -801 998 0 +-254 -960 385 0 +-613 81 -822 0 +725 -470 511 0 +335 713 -770 0 +928 390 57 0 +183 -237 277 0 +367 -855 649 0 +249 302 979 0 +577 349 -841 0 +883 340 978 0 +-153 -931 133 0 +465 897 -186 0 +80 26 885 0 +639 386 -674 0 +37 -663 -421 0 +709 749 14 0 +-173 409 -610 0 +-228 -154 534 0 +242 -585 403 0 +-295 -961 978 0 +-284 -915 -588 0 +-895 478 -595 0 +-166 -905 -538 0 +194 449 -232 0 +-355 331 -188 0 +727 202 246 0 +972 -764 350 0 +417 91 -841 0 +864 315 -239 0 +-610 -189 506 0 +69 -354 -365 0 +441 61 -981 0 +75 193 -883 0 +-918 562 -351 0 +686 304 885 0 +595 -30 -446 0 +-997 -338 -487 0 +355 217 -25 0 +104 -311 420 0 +728 -407 748 0 +784 -972 -554 0 +750 791 421 0 +996 -488 -214 0 +791 -797 -480 0 +-944 -999 401 0 +-505 -46 341 0 +-453 759 -660 0 +598 157 -984 0 +-884 52 766 0 +727 767 -869 0 +-663 575 -382 0 +473 -262 -511 0 +475 -78 325 0 +-948 808 -311 0 +-957 -280 29 0 +-19 -685 150 0 +454 500 718 0 +-646 638 278 0 +-287 -705 392 0 +727 -409 677 0 +936 -134 340 0 +-385 -185 -599 0 +774 305 -223 0 +703 184 628 0 +-20 733 -158 0 +-72 -612 -154 0 +965 512 -627 0 +-820 -887 905 0 +-506 364 -368 0 +-224 -572 -74 0 +-173 -724 -946 0 +-735 -856 422 0 +231 -145 704 0 +-739 126 -503 0 +128 525 -716 0 +-491 -261 -838 0 +-25 -325 -811 0 +-160 185 295 0 +631 -61 -692 0 +633 642 -476 0 +703 -681 264 0 +-964 -595 537 0 +-504 -664 615 0 +504 336 -996 0 +434 551 589 0 +-607 604 313 0 +81 -600 -27 0 +-729 -810 977 0 +-716 603 -838 0 +645 -320 297 0 +-12 124 -152 0 +-436 -342 935 0 +-175 -195 925 0 +-786 -848 -276 0 +947 -761 328 0 +539 967 -986 0 +-809 -912 489 0 +999 549 966 0 +74 880 347 0 +596 -863 -22 0 +-249 -521 -60 0 +-977 654 887 0 +545 -813 204 0 +-317 -152 543 0 +515 965 935 0 +153 6 -86 0 +554 -773 100 0 +97 -875 94 0 +-363 852 -331 0 +778 -28 -503 0 +-344 567 -966 0 +-262 -73 997 0 +36 666 -675 0 +345 591 -426 0 +61 -869 -606 0 +605 -934 229 0 +-279 89 -103 0 +-449 -479 -652 0 +365 -570 -651 0 +229 201 479 0 +-352 238 -324 0 +-948 480 -19 0 +-120 -605 -127 0 +-316 875 923 0 +-243 -684 -543 0 +331 640 -429 0 +907 359 -272 0 +-757 446 -794 0 +-118 -684 -570 0 +413 154 -141 0 +270 -850 75 0 +-189 514 797 0 +-685 193 -4 0 +-849 -588 963 0 +489 19 -117 0 +-192 353 496 0 +148 653 206 0 +-475 -610 848 0 +558 919 489 0 +-62 -726 566 0 +-747 -844 772 0 +-342 15 -371 0 +115 -42 150 0 +-724 -171 915 0 +772 -292 470 0 +79 -848 -941 0 +-797 -592 -159 0 +418 247 763 0 +-696 -784 590 0 +-625 -696 -49 0 +134 791 -559 0 +708 -792 -775 0 +-367 -62 -264 0 +-607 -264 -195 0 +663 -500 -307 0 +924 584 458 0 +785 -117 -100 0 +-229 -687 -883 0 +910 -642 -830 0 +149 775 -175 0 +38 498 -827 0 +-621 -212 415 0 +-793 -42 -221 0 +140 886 -74 0 +-654 635 419 0 +624 585 798 0 +401 -604 -820 0 +-279 23 629 0 +-890 783 -106 0 +-842 -506 108 0 +477 864 830 0 +-109 -470 178 0 +443 -598 -328 0 +493 -687 -562 0 +-757 -85 -296 0 +-462 254 -128 0 +-307 -651 653 0 +-47 -560 436 0 +-161 540 597 0 +-39 510 -708 0 +954 594 536 0 +994 106 -969 0 +446 431 -196 0 +-342 -719 -451 0 +946 -547 -167 0 +-678 -968 -817 0 +643 941 -254 0 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp100.dat b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp100.dat new file mode 100644 index 0000000..9d358cf --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp100.dat @@ -0,0 +1,307 @@ +100 + +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 + +5 +10 +15 +20 +25 +29 +34 +39 +44 +49 +53 +58 +63 +68 +73 +77 +82 +87 +92 +97 +101 +106 +111 +116 +121 +125 +130 +135 +140 +145 +149 +154 +159 +164 +169 +173 +178 +183 +188 +193 +197 +202 +207 +212 +217 +221 +226 +231 +236 +241 +245 +250 +255 +260 +265 +269 +274 +279 +284 +289 +293 +298 +303 +308 +313 +317 +322 +327 +332 +337 +341 +346 +351 +356 +361 +365 +370 +375 +380 +385 +389 +394 +399 +404 +409 +413 +418 +423 +428 +433 +437 +442 +447 +452 +457 +461 +466 +471 +476 +481 + +60.000000 +40.000000 +7.000000 +3.000000 +50.000000 +120.000000 +80.000000 +7.000000 +3.000000 +100.000000 +180.000000 +120.000000 +7.000000 +3.000000 +150.000000 +240.000000 +160.000000 +7.000000 +3.000000 +200.000000 +300.000000 +200.000000 +7.000000 +3.000000 +250.000000 +360.000000 +240.000000 +7.000000 +3.000000 +300.000000 +420.000000 +280.000000 +7.000000 +3.000000 +350.000000 +480.000000 +320.000000 +7.000000 +3.000000 +400.000000 +540.000000 +360.000000 +7.000000 +3.000000 +450.000000 +600.000000 +400.000000 +7.000000 +3.000000 +500.000000 +660.000000 +440.000000 +7.000000 +3.000000 +550.000000 +720.000000 +480.000000 +7.000000 +3.000000 +600.000000 +780.000000 +520.000000 +7.000000 +3.000000 +650.000000 +840.000000 +560.000000 +7.000000 +3.000000 +700.000000 +900.000000 +600.000000 +7.000000 +3.000000 +750.000000 +960.000000 +640.000000 +7.000000 +3.000000 +800.000000 +1020.000000 +680.000000 +7.000000 +3.000000 +850.000000 +1080.000000 +720.000000 +7.000000 +3.000000 +900.000000 +1140.000000 +760.000000 +7.000000 +3.000000 +950.000000 +1200.000000 +800.000000 +7.000000 +3.000000 +1000.000000 + +200 +) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp20.dat b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp20.dat new file mode 100644 index 0000000..9dde3f3 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/MTTP-instances/mttp20.dat @@ -0,0 +1,84 @@ +20 + +2 +4 +1 +7 +4 +3 +5 +2 +4 +7 +2 +9 +8 +6 +1 +4 +9 +7 +8 +2 + +3 +5 +6 +8 +10 +15 +16 +20 +25 +29 +30 +36 +49 +59 +80 +81 +89 +97 +100 +105 + +15.000000 +20.000000 +16.000000 +19.000000 +10.000000 +25.000000 +17.000000 +18.000000 +21.000000 +17.000000 +31.000000 +2.000000 +26.000000 +42.000000 +50.000000 +19.000000 +17.000000 +21.000000 +22.000000 +13.000000 + + +00001111111111111111 70.000000 + +01001110111011111111 70.000000 + +01101101101011111111 70.000000 + +01101101111011110111 70.000000 + +01101101111111101111 70.000000 + +10001111111011111110 70.000000 + +10100111011111111111 70.000000 + +10100111111011101111 70.000000 + +10100111111111111011 70.000000 +) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/format.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/format.txt new file mode 100644 index 0000000..179a679 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/format.txt @@ -0,0 +1 @@ +// dimension of the bitstring. diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/onemax10.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/onemax10.txt new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/ONEMAX-instances/onemax10.txt @@ -0,0 +1 @@ +10 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS10.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS20.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/RAS20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/format.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RAS-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RND-instances/rnd149.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RND-instances/rnd149.txt new file mode 100644 index 0000000..15c44e9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/RND-instances/rnd149.txt @@ -0,0 +1 @@ +149 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH10.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH20.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/SPH20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/format.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/SPHERE-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/format.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/format.txt new file mode 100644 index 0000000..abccebe --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/format.txt @@ -0,0 +1,3 @@ +// Number of customers, Vehicle capacity, Maximum time per route, Service time and best known cost +// Depot Coordenates +// Customer coordenates and demand diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpinfo.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpinfo.txt new file mode 100644 index 0000000..a63a622 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpinfo.txt @@ -0,0 +1,47 @@ +There are currently 24 data files. + +The first set of data files are the 10 test problems from +Chapter 9 of S.Eilon, C.D.T.Watson-Gandy and N.Christofides +"Distribution management: mathematical modelling and +practical analysis" Griffin, London 1971. + +Test problems 1, 2, ..., 10 from Chapter 9 are available +in files vrp1, vrp2, ..., vrp10 respectively. + +The format of these data files is apparent from the tables +of data given in the above reference. + +The second set of data files are the 14 test problems from +Chapter 11 of N.Christofides, A.Mingozzi, P.Toth and C.Sandi +(eds) "Combinatorial optimization", John Wiley, Chichester 1979. + +Test problems 1, 2, ..., 14 from Chapter 11 are available +in files vrpnc1, vrpnc2, ..., vrpnc14 respectively. + +The format of these data files is: +number of customers, vehicle capacity, maximum route time, drop time +depot x-coordinate, depot y-coordinate +for each customer in turn: x-coordinate, y-coordinate, quantity + +Both sets of files are of size 15Kb (approximately). + + + +OTHER SOURCES + +Test data for vehicle routing problems is also available +using the Web from http://www-apache.imag.fr/~paugerat/VRP/INSTANCES + +A variety of vehicle routing problems are also available from the +elib library: +telnet elib.zib.de and login as elib +WWW access available at: +ftp://ftp.zib.de/pub/Packages/mp-testdata/index.html + + + +A full listing of the problem areas covered by OR-library can +be found in the file info + +ftp access available at mscmga.ms.ic.ac.uk +WWW access available at http://mscmga.ms.ic.ac.uk/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc1.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc1.txt new file mode 100644 index 0000000..fb9bd54 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc1.txt @@ -0,0 +1,52 @@ + 50 160 999999 0 524.61 + 30 40 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc10.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc10.txt new file mode 100644 index 0000000..bd6fc1b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc10.txt @@ -0,0 +1,201 @@ + 199 200 200 10 865.94 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc11.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc11.txt new file mode 100644 index 0000000..adea50e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc11.txt @@ -0,0 +1,122 @@ + 120 200 999999 0 866.37 + 10 45 + 25 1 25 + 25 3 7 + 31 5 13 + 32 5 6 + 31 7 14 + 32 9 5 + 34 9 11 + 46 9 19 + 35 7 5 + 34 6 15 + 35 5 15 + 47 6 17 + 40 5 13 + 39 3 12 + 36 3 18 + 73 6 13 + 73 8 18 + 24 36 12 + 76 6 17 + 76 10 4 + 76 13 7 + 78 3 12 + 78 9 13 + 79 3 8 + 79 5 16 + 79 11 15 + 82 3 6 + 82 7 5 + 90 15 9 + 84 3 11 + 84 5 10 + 84 9 3 + 85 1 7 + 87 5 2 + 85 8 4 + 87 7 4 + 86 41 18 + 86 44 14 + 86 46 12 + 85 55 17 + 89 43 20 + 89 46 14 + 89 52 16 + 92 42 10 + 92 52 9 + 94 42 11 + 94 44 7 + 94 48 13 + 96 42 5 + 99 46 4 + 99 50 21 + 83 80 13 + 83 83 11 + 85 81 12 + 85 85 14 + 85 89 10 + 87 80 8 + 87 86 16 + 90 77 19 + 90 88 5 + 93 82 17 + 93 84 7 + 93 89 16 + 94 86 14 + 95 80 17 + 99 89 13 + 37 83 17 + 50 80 13 + 35 85 14 + 35 87 16 + 44 86 7 + 46 89 13 + 46 83 9 + 46 87 11 + 46 89 35 + 48 83 5 + 50 85 28 + 50 88 7 + 54 86 3 + 54 90 10 + 10 35 7 + 10 40 12 + 18 30 11 + 17 35 10 + 16 38 8 + 14 40 11 + 15 42 21 + 11 42 4 + 18 40 15 + 21 39 16 + 20 40 4 + 18 41 16 + 20 44 7 + 22 44 10 + 16 45 9 + 20 45 11 + 25 45 17 + 30 55 12 + 20 50 11 + 22 51 7 + 18 49 9 + 16 48 11 + 20 55 12 + 18 53 7 + 14 50 8 + 15 51 6 + 16 54 5 + 28 33 12 + 33 38 13 + 30 50 7 + 13 40 7 + 15 36 8 + 18 31 11 + 25 37 13 + 30 46 11 + 25 52 10 + 16 33 7 + 25 35 4 + 5 40 20 + 5 50 13 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc12.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc12.txt new file mode 100644 index 0000000..939f5dd --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc12.txt @@ -0,0 +1,102 @@ + 100 200 999999 0 1541.14 + 40 50 + 45 68 10 + 45 70 30 + 42 66 10 + 42 68 10 + 42 65 10 + 40 69 20 + 40 66 20 + 38 68 20 + 38 70 10 + 35 66 10 + 35 69 10 + 25 85 20 + 22 75 30 + 22 85 10 + 20 80 40 + 20 85 40 + 18 75 20 + 15 75 20 + 15 80 10 + 30 50 10 + 30 52 20 + 28 52 20 + 28 55 10 + 25 50 10 + 25 52 40 + 25 55 10 + 23 52 10 + 23 55 20 + 20 50 10 + 20 55 10 + 10 35 20 + 10 40 30 + 8 40 40 + 8 45 20 + 5 35 10 + 5 45 10 + 2 40 20 + 0 40 30 + 0 45 20 + 35 30 10 + 35 32 10 + 33 32 20 + 33 35 10 + 32 30 10 + 30 30 10 + 30 32 30 + 30 35 10 + 28 30 10 + 28 35 10 + 26 32 10 + 25 30 10 + 25 35 10 + 44 5 20 + 42 10 40 + 42 15 10 + 40 5 30 + 40 15 40 + 38 5 30 + 38 15 10 + 35 5 20 + 50 30 10 + 50 35 20 + 50 40 50 + 48 30 10 + 48 40 10 + 47 35 10 + 47 40 10 + 45 30 10 + 45 35 10 + 95 30 30 + 95 35 20 + 53 30 10 + 92 30 10 + 53 35 50 + 45 65 20 + 90 35 10 + 88 30 10 + 88 35 20 + 87 30 10 + 85 25 10 + 85 35 30 + 75 55 20 + 72 55 10 + 70 58 20 + 68 60 30 + 66 55 10 + 65 55 20 + 65 60 30 + 63 58 10 + 60 55 10 + 60 60 10 + 67 85 20 + 65 85 40 + 65 82 10 + 62 80 30 + 60 80 10 + 60 85 30 + 58 75 20 + 55 80 10 + 55 85 20 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc13.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc13.txt new file mode 100644 index 0000000..975ff61 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc13.txt @@ -0,0 +1,122 @@ + 120 200 720 50 1162.55 + 10 45 + 25 1 25 + 25 3 7 + 31 5 13 + 32 5 6 + 31 7 14 + 32 9 5 + 34 9 11 + 46 9 19 + 35 7 5 + 34 6 15 + 35 5 15 + 47 6 17 + 40 5 13 + 39 3 12 + 36 3 18 + 73 6 13 + 73 8 18 + 24 36 12 + 76 6 17 + 76 10 4 + 76 13 7 + 78 3 12 + 78 9 13 + 79 3 8 + 79 5 16 + 79 11 15 + 82 3 6 + 82 7 5 + 90 15 9 + 84 3 11 + 84 5 10 + 84 9 3 + 85 1 7 + 87 5 2 + 85 8 4 + 87 7 4 + 86 41 18 + 86 44 14 + 86 46 12 + 85 55 17 + 89 43 20 + 89 46 14 + 89 52 16 + 92 42 10 + 92 52 9 + 94 42 11 + 94 44 7 + 94 48 13 + 96 42 5 + 99 46 4 + 99 50 21 + 83 80 13 + 83 83 11 + 85 81 12 + 85 85 14 + 85 89 10 + 87 80 8 + 87 86 16 + 90 77 19 + 90 88 5 + 93 82 17 + 93 84 7 + 93 89 16 + 94 86 14 + 95 80 17 + 99 89 13 + 37 83 17 + 50 80 13 + 35 85 14 + 35 87 16 + 44 86 7 + 46 89 13 + 46 83 9 + 46 87 11 + 46 89 35 + 48 83 5 + 50 85 28 + 50 88 7 + 54 86 3 + 54 90 10 + 10 35 7 + 10 40 12 + 18 30 11 + 17 35 10 + 16 38 8 + 14 40 11 + 15 42 21 + 11 42 4 + 18 40 15 + 21 39 16 + 20 40 4 + 18 41 16 + 20 44 7 + 22 44 10 + 16 45 9 + 20 45 11 + 25 45 17 + 30 55 12 + 20 50 11 + 22 51 7 + 18 49 9 + 16 48 11 + 20 55 12 + 18 53 7 + 14 50 8 + 15 51 6 + 16 54 5 + 28 33 12 + 33 38 13 + 30 50 7 + 13 40 7 + 15 36 8 + 18 31 11 + 25 37 13 + 30 46 11 + 25 52 10 + 16 33 7 + 25 35 4 + 5 40 20 + 5 50 13 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc14.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc14.txt new file mode 100644 index 0000000..02946d9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc14.txt @@ -0,0 +1,102 @@ + 100 200 1040 90 1395.85 + 40 50 + 45 68 10 + 45 70 30 + 42 66 10 + 42 68 10 + 42 65 10 + 40 69 20 + 40 66 20 + 38 68 20 + 38 70 10 + 35 66 10 + 35 69 10 + 25 85 20 + 22 75 30 + 22 85 10 + 20 80 40 + 20 85 40 + 18 75 20 + 15 75 20 + 15 80 10 + 30 50 10 + 30 52 20 + 28 52 20 + 28 55 10 + 25 50 10 + 25 52 40 + 25 55 10 + 23 52 10 + 23 55 20 + 20 50 10 + 20 55 10 + 10 35 20 + 10 40 30 + 8 40 40 + 8 45 20 + 5 35 10 + 5 45 10 + 2 40 20 + 0 40 30 + 0 45 20 + 35 30 10 + 35 32 10 + 33 32 20 + 33 35 10 + 32 30 10 + 30 30 10 + 30 32 30 + 30 35 10 + 28 30 10 + 28 35 10 + 26 32 10 + 25 30 10 + 25 35 10 + 44 5 20 + 42 10 40 + 42 15 10 + 40 5 30 + 40 15 40 + 38 5 30 + 38 15 10 + 35 5 20 + 50 30 10 + 50 35 20 + 50 40 50 + 48 30 10 + 48 40 10 + 47 35 10 + 47 40 10 + 45 30 10 + 45 35 10 + 95 30 30 + 95 35 20 + 53 30 10 + 92 30 10 + 53 35 50 + 45 65 20 + 90 35 10 + 88 30 10 + 88 35 20 + 87 30 10 + 85 25 10 + 85 35 30 + 75 55 20 + 72 55 10 + 70 58 20 + 68 60 30 + 66 55 10 + 65 55 20 + 65 60 30 + 63 58 10 + 60 55 10 + 60 60 10 + 67 85 20 + 65 85 40 + 65 82 10 + 62 80 30 + 60 80 10 + 60 85 30 + 58 75 20 + 55 80 10 + 55 85 20 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc2.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc2.txt new file mode 100644 index 0000000..214012a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc2.txt @@ -0,0 +1,77 @@ + 75 140 999999 0 835.26 + 40 40 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 + 15 56 22 + 29 39 12 + 54 38 19 + 55 57 22 + 67 41 16 + 10 70 7 + 6 25 26 + 65 27 14 + 40 60 21 + 70 64 24 + 64 4 13 + 36 6 15 + 30 20 18 + 20 30 11 + 15 5 28 + 50 70 9 + 57 72 37 + 45 42 30 + 38 33 10 + 50 4 8 + 66 8 11 + 59 5 3 + 35 60 1 + 27 24 6 + 40 20 10 + 40 37 20 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc3.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc3.txt new file mode 100644 index 0000000..8bfcc47 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc3.txt @@ -0,0 +1,102 @@ + 100 200 999999 0 826.14 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc4.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc4.txt new file mode 100644 index 0000000..3faf64a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc4.txt @@ -0,0 +1,152 @@ + 150 200 999999 0 819.56 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc5.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc5.txt new file mode 100644 index 0000000..3cacfb7 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc5.txt @@ -0,0 +1,201 @@ + 199 200 999999 0 1042.11 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc6.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc6.txt new file mode 100644 index 0000000..449fd5c --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc6.txt @@ -0,0 +1,52 @@ + 50 160 200 10 1028.42 + 30 40 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc7.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc7.txt new file mode 100644 index 0000000..1b8aa97 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc7.txt @@ -0,0 +1,77 @@ + 75 140 160 10 1291.45 + 40 40 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 + 15 56 22 + 29 39 12 + 54 38 19 + 55 57 22 + 67 41 16 + 10 70 7 + 6 25 26 + 65 27 14 + 40 60 21 + 70 64 24 + 64 4 13 + 36 6 15 + 30 20 18 + 20 30 11 + 15 5 28 + 50 70 9 + 57 72 37 + 45 42 30 + 38 33 10 + 50 4 8 + 66 8 11 + 59 5 3 + 35 60 1 + 27 24 6 + 40 20 10 + 40 37 20 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc8.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc8.txt new file mode 100644 index 0000000..0383887 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc8.txt @@ -0,0 +1,102 @@ + 100 200 230 10 555.43 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc9.txt b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc9.txt new file mode 100644 index 0000000..1910e87 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/ProblemInstances/VRP-instances/vrpnc9.txt @@ -0,0 +1,152 @@ + 150 200 200 10 909.68 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/README.md b/ProyectoFinal/AlgoritmoGenetico/malva/README.md new file mode 100644 index 0000000..53d6d5d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/README.md @@ -0,0 +1,278 @@ +## What is Malva? + +Malva is a fork of the MALLBA project. MALLBA is an effort to develop, in an integrated way, a +library of skeletons for combinatorial optimization (including exact, heuristic and hybrid methods) +that can deal with parallelism in a user-friendly and, at the same time, efficient manner. +Its three target environments are sequential computers, LANs of workstations and WANs. The main features of MALLBA are: + +* Integration of all the skeletons under the same design principles. +* Facility to switch from sequential to parallel optimization engines. +By providing sequential implementations users obtain parallel implementations. +* Cooperation between engines makes possible to provide more powerful hybrid engines. +* Ready to use on commodity machines. +* Flexible and extensible software architecture. New skeletons can easily be added, alternative communication layers +can be used, etc. + +## How to install and compile Malva + +First of all, you have to install MPICH library. Get the instructions here: http://www.mpich.org/. In OSX, you can just +type: + + brew install mpich --disable-fortran + +Disabling Fortran is needed since we are working with C++ instead of Fortran. + +After that, you have to clone this repository using `git clone https://github.com/gabrielfagundez/malva`, and configure Malva modifying the `environment` file. + +Then, execute the following command: + + make all + +Your Malva directory should contain the following content after the make: + +``` + -rw-r--r-- 1 user users 378 sep 24 09:39 Makefile + drwxr-xr-x 4 user users 4096 sep 24 09:48 ProblemInstances + -rw-r--r-- 1 user users 345 sep 24 16:29 environment + drwxr-xr-x 2 user users 4096 sep 24 16:43 inc + drwxr-xr-x 2 user users 4096 sep 24 17:49 lib + drwxr-xr-x 5 user users 4096 sep 24 09:41 rep + drwxr-xr-x 2 user users 4096 sep 24 17:49 src +``` + +## Testing the installation + +Go to `MALLBA_DIR/rep_new/CHC` or `MALLBA_DIR/rep_new/GA` and execute `make SEQ` or `make LAN`. If you have in your console +the result of the execution, everything looks great! + +## Important notes + +The only new fully-functional algorithms are the GA and the CHC. + +## Architecture + +Mallba skeletons are based on the separation of two concepts: the concrete problem to be solved and the general +resolution method to be used. They can be seen as generic templates that just need to be instantiated with the +features of a problem in order to solve it. All features related to the selected generic resolution method and +its interaction with the concrete problem are implemented by the skeleton. While the particular features related +to the problem must be given by the user, the knowledge to parallelize the execution of the resolution method is +implemented in the skeleton, so that users do not need to deal with parallelism issues. + +The design of the Mallba library focuses on easy to use skeletons and general and efficient implementations. +To achieve both objectives, the C++ programming language was selected due to its high level, modularity, +flexibility and efficiency features. We have reduced to a minimum the use of inheritance and virtual methods in +order to provide better efficiency and ease of use. To instantiate most problems, a basic knowledge of C++ is enough, +and only sequential code without side effects is needed. + +Skeletons are implemented by a set of required and provided C++ classes that represent an abstraction of the entities +participating in the resolution method. The provided classes implement internal aspects of the skeleton in a +problem-independent way. The required classes specify information and behavior related to the problem. +This conceptual separation allows us to define required classes with a fixed interface but without any implementation, +so that provided classes can use required classes in a generic way. + +More specifically, each skeleton includes the Problem and Solution required classes, that encapsulate the +problem-dependent entities needed by the resolution method. The Problem class abstracts the features of the +problem that are relevant to the selected optimization method. The Solution class abstracts the features of the +feasible solutions that are relevant to the selected resolution method. Depending on the skeleton, other classes +may be required. On the other hand, each skeleton offers two provided classes: Solver and SetUpParams. The former +abstracts the selected resolution method. The later contains the setup parameters needed to perform the execution +(e.g. number of iterations, number of independent runs, parameters guiding the search, etc.). The Solver class provides +methods to run the resolution scheme and methods to consult its progress or change its state. The only information the +solver needs is an instance of the problem to solve and the setup parameters. In order to enable an skeleton to have +different solver engines, the Solver class defines a unique interface and provides several subclasses that provide +different sequential and parallel implementations (Solver_Seq, Solver_Lan and Solver_Wan). In Fig. 1 is shown the +common design of Mallba skeletons. + + + +## Implementation + +The implementation of each skeleton is contained in three files: + +* <skeleton>.hh: The file containing the definition of all classes (provides and requires). +* <skeleton>.pro.cc: The file containing the source code of the classes needed for the internal implementation of the method. +* <skeleton>.req.cc: The source file where all the required classes will be implemented. + +In additional, the user must configure the method parameters in the file <skeleton>.cfg. + +## Supported Algorithms + +### Genetic Algorithm + +A Genetic Algorithm is an evolutionary computation technique inspired by the principles of natural selection to search +a solution space. It evolves a population of individuals encoded as chromosomes by creating new generations of +offsprings through an iterative process until some convergence criteria or conditions are met. The best chromosome +generated is then decoded, providing the corresponding solution. The underlying reproduction process is mainly aimed +at improving the fitness of individuals, a measure of profit, utility or goodness to be maximized (or minimized) while +exploring the solution space. The algorithm applies stochastic operators such as selection, crossover, and mutation, +on an initially random population in order to compute a new generation of individuals. The whole process is sketched +in the following figure. + +``` + 1 t = 0 + 2 initialize P(t) + 3 evaluate structures in P(t) + 4 while not end do + 5 t = t + 1 + 6 select C(t) from P(t-1) + 7 recombine structures in C(t) forming C'(t) + 8 mutate structures in C'(t) forming C''(t) + 9 evaluate structures in C''(t) +10 replace P(t) from C''(t) and/or P(t-1) +``` + +It can be seen that the algorithm comprises three major stages: selection, reproduction and replacement. During the +selection stage, a temporary population is created in which the fittest individuals (those corresponding to the best +solutions contained in the population) have a higher number of instances than those less fit (natural selection). The +reproductive operators are applied to the individuals in this population yielding a new population. Finally, individuals +of the original population are substituted by the new created individuals. This replacement usually tries to keep the +best individuals deleting the worst ones. The whole process is repeated until a certain termination criterion is +achieved (usually after a given number of iterations). + +The Genetic Algorithm skeleton (GA) requires the classes: + +* Problem +* Solution +* Crossover +* Mutation + +The class Problem corresponds to the definition of a problem instance. The skeleton filler must provide a complete +definition of this class. + +The class Solution corresponds to the definition of a solution (feasible or not) of a problem instance. The skeleton +filler must provide a complete definition of the class Solution. + +The class Crossover corresponds to the definition of a crossover operator. The skeleton filler must provide a complete +definition of this class. + +And finally, the class Mutation corresponds to the definition of a mutation operator. The skeleton filler must provide +a complete definition of this class. + +In adition, the user must configure the following algorithm parameters (in file GA.cfg): + +* number of independent runs. +* number of generations. +* size of population. +* size of offsprings in each generation. +* replace mode (if replaces parents for offsprings, or only offsprings may be new parents). +* Selection operators parameters (selection of parents and selection of offsprings parameters). +* Intra operators parameters (crossover and mutation parameters). +* Inter operators (operators to apply between sub-populations) parameters: operator number, operator rate, number of individuals and selection of individual to send and replace. +* Parallel Configuracion: interval of generation to refresh global state, running mode (synchronized or asyncronized) and interval of generations to check solutions from other populations. + +There are several basic steps to running a problem solve with GA skeleton: + +* Change to the problem directory + + `cd Mallba/rep/GA/problem` + +* Compile skeleton. + + `make` + +* Configure algorithm parameters (GA.cfg file) + +* Run problem: +Sequential Version: + +``` +make SEQ + or +MainSeq GA.cfg_path instance_path res_file_path +``` + +Parallel Version: + +Configure Config.cfg file. +Configure pgfileLan (or pgfileWan) : machines where we run the program. +Run + +``` +make LAN + or +make WAN +``` + +### CHC + +A CHC is a non-traditional GA which combines a conservative selection strategy (that always preserves the best +individuals found so far) with a highly disruptive recombination (HUX) that produces offsprings that are maximally +different from their two parents. The traditional though of preferring a recombination operator with a low disrupting +properties may not hold when such a conservative selection strategy is used. On the contrary, certain highly disruptive +crossover operator provide more effective search in many problems, which represents the core idea behind the + +CHC search method. This algorithm introduce a new bias against mating individuals who are too similar (incest +prevention). Mutation is not performed, instead, a restart process re-introduces diversity whenever convergence is +detected. + +``` + 1 t = 0 + 2 initialize P(t) + 3 evaluate structures in P(t) + 4 while not end do + 5 t = t + 1 + 6 select: C(t) = P(t-1) + 7 recombine: C'(t) = 'incest prevention' + HUX(C'(t)) + 8 evaluate structures in C'(t) + 9 replace P(t) from C''(t) and P(t-1) +10 if convergence(P(t)) +11 diverge P(t) +``` + +The CHC method skeleton (CHC) requires the classes: + +* Problem +* Solution + +The class Problem corresponds to the definition of a problem instance. The skeleton filler must provide a complete +definition of this class. + +And finally, the class Solution corresponds to the definition of a solution (feasible or not) of a problem instance. +The skeleton filler must provide a complete definition of the class Solution. + +In adition, the user must configure the following algorithm parameters (in file CHC.cfg): + +* number of independent runs. +* number of generations. +* size of population. +* Selection operator parameters (selection of new parents and the diverge method that the algorithm uses whenever the +convergence is detected). +* Intra operators parameters (crossover and mutation parameters). +* Inter operators (operators to apply between sub-populations) parameters: operator number, operator rate, number of +individuals and selection of individual to send and replace. +* Parallel Configuracion: interval of generation to refresh global state, running mode (synchronized or asyncronized) +and interval of generations to check solutions from other populations. + +There are several basic steps to running a problem solve with CHC skeleton: + +* Change to the problem directory + + `cd Mallba/rep/CHC/problem` + +* Compile skeleton + + `make` + +* Configure algorithm parameters (CHC.cfg file) + +* Run problem: + +Sequential Version: + +``` +make SEQ + or +MainSeq GA.cfg_path instance_path res_file_path +``` + +Parallel Version: + +Configure Config.cfg file. +Configure pgfileLan (or pgfileWan) : machines where we run the program. +Run + +``` +make LAN + or +make WAN +``` diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/environment b/ProyectoFinal/AlgoritmoGenetico/malva/environment new file mode 100644 index 0000000..4976de6 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/environment @@ -0,0 +1,19 @@ +# Malva Configuration. +MALLBA_DIR=/ens/home01/g/gonzalo.menendez/AEPractico/malva + +# MPI library +MPI_BIN=/lib64/mpich/bin +# Malva information +MALLBA_INC=${MALLBA_DIR}/src +MALLBA_LIB=${MALLBA_DIR}/lib +MALLBA_SRC=${MALLBA_DIR}/src +MALLBA_REP=${MALLBA_DIR}/rep + +# Run variables +CXX=$(MPI_BIN)/mpic++ +RUN=$(MPI_BIN)/mpirun + +# Other options: -g for debugging and -pg for profiling +CPPFLAGS=-I$(MALLBA_INC) -Wno-deprecated -O3 +LDFLAGS=-L$(MALLBA_LIB) +LOADLIBES=-lmallba -lm diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/inc/Mallba b/ProyectoFinal/AlgoritmoGenetico/malva/inc/Mallba new file mode 100644 index 0000000..5cd551c --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/inc/Mallba @@ -0,0 +1 @@ +../src \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/inc/inc.env b/ProyectoFinal/AlgoritmoGenetico/malva/inc/inc.env new file mode 100644 index 0000000..3976b86 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/inc/inc.env @@ -0,0 +1 @@ +ln -s ../src Mallba diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/lib/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/lib/Makefile new file mode 100644 index 0000000..5bacf25 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/lib/Makefile @@ -0,0 +1,8 @@ +all: + rm -f libmallba.a + ar -r libmallba.a ../src/*.o + ranlib libmallba.a + +clean: + rm -f libmallba.a + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/lib/libmallba.a b/ProyectoFinal/AlgoritmoGenetico/malva/lib/libmallba.a new file mode 100644 index 0000000000000000000000000000000000000000..db7f3cab7df60324f9676e75019a0ef727333a3e GIT binary patch literal 34998 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.cfg new file mode 100644 index 0000000..0f6c796 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.cfg @@ -0,0 +1,15 @@ +10 // number of independent runs +100 // number of generations +60 // number of individuals +1 // display state ? +Selection-Parameters // selections to apply +0.9 1 0.5 // selection parameter , diverge operator & its probability +Intra-Operators // operators to apply in the population +0 0.8 // crossover & its probability +Inter-Operators // operators to apply between this population and anothers +0 25 5 1 3 1 5 // operator number, operator rate, number of individuals, selection of indidivual to send and remplace +LAN-configuration +101 // refresh global state +1 // 0: running in asynchronized mode / 1: running in synchronized mode +1 // interval of generations to check solutions from other populations + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.hh new file mode 100644 index 0000000..0c89fe4 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.hh @@ -0,0 +1,909 @@ +/********************************************************************************************************* +*** *** +*** CHC Skeleton v1.5 *** +*** Developed by: Gabriel Jesús Luque Polo *** +*** *** +*** Last Update: 30-01-2004 *** +*** *** +**********************************************************************************************************/ + +#ifndef INC_CHC +#define INC_CHC +#include "CHCstructures.hh" + +skeleton CHC +{ +#define MAX_USER_OP 5 +#define MAX_PROB_PER_OP 5 + + provides class SetUpParams; + provides class Statistics; + provides class Population; + provides class Intra_Operator; + provides class Crossover; + provides class Diverge; + provides class Inter_Operator; + provides class Migration; + provides class Selection; + provides class Selection_New_Population; + provides class Selection_Parents; + provides class Operator_Pool; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + provides class StopCondition; + + requires class Problem; + requires class Solution; + requires class UserStatistics; + requires class User_Operator; + requires class StopCondition_1; + requires bool terminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + int dimension() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness () const; + unsigned int size() const; + + int lengthInBits() const; + void flip(const int index); + bool equalb(const int index,Solution &s); + void swap(const int index, Solution &s); + void invalid(); + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + unsigned long nb_evaluation_best_found_trial; + unsigned long nb_iteration_best_found_trial; + double best_cost_trial; + double worst_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Intra_Operator ( clase abstracta ) -------------------------------------------------------------- + + provides class Intra_Operator + { + protected: + unsigned int _number_operator; + float *probability; + + public: + Intra_Operator(const unsigned int _number_op); + virtual ~Intra_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const Intra_Operator& intra); + + virtual void execute(Rarray<Solution*>& sols) const=0; + virtual void setup(char line[MAX_BUFFER]) = 0; + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const=0; + virtual void UpdateFromState(const StateCenter& _sc)=0; + }; + +// Crossover ---------------------------------------------------------------------------------- + + provides class Crossover: public Intra_Operator + { + public: + Crossover(); + virtual ~Crossover(); + + friend ostream& operator << (ostream& os, const Crossover& cross); + + void cross(Solution &sol1,Solution &sol2) const; + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Diverge ---------------------------------------------------------------------------------- + + provides class Diverge: public Intra_Operator + { + public: + Diverge(); + virtual ~Diverge(); + + friend ostream& operator<< (ostream& os, const Diverge& diverge); + + void diverge(Solution& s) const; + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// User_Operator ---------------------------------------------------------------------------------- + + requires class User_Operator: public Intra_Operator + { + public: + User_Operator(const unsigned int _number_op); + virtual ~User_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const User_Operator& User_Operator); + + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// StopCondition ----------------------------------------------------------------------------------- + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + +// StopCondition_1 ----------------------------------------------------------------------------------- + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _nb_evolution_steps; + unsigned long _nb_iteration_steps; + unsigned int _population_size; // number of individuals + bool _display_state; + + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _check_asynchronous; + + // selection of parents and offsprings + mutable unsigned int _select_parents; + mutable unsigned int _select_offsprings; + + Rlist<unsigned int> _intra_operators; + Rlist<unsigned int> _inter_operators; + + Operator_Pool& _pool; + + public: + SetUpParams (Operator_Pool& pool); + Operator_Pool& pool() const; + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long nb_evolution_steps() const; + const unsigned int population_size() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int check_asynchronous() const; + + void independent_runs(const unsigned int val); + void nb_evolution_steps(const unsigned long val); + void population_size(const unsigned int val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void check_asynchronous(const unsigned int val); + + // gets the i-th operator of inter-population + const unsigned int inter_operator_index(const unsigned int index) const; + const unsigned int inter_operators_size() const; + + // gets the i-th operator of intra-population + const unsigned int intra_operator_index(const unsigned int index) const; + const unsigned int intra_operators_size() const; + + const unsigned int select_parents() const; + const unsigned int select_offsprings() const; + + void select_parents(const unsigned int val); + void select_offsprings(const unsigned int val); + + void RefreshState(const StateCenter& _sc) const; + void UpdateFromState(const StateCenter& _sc) const; + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_generation; + unsigned long nb_evaluation; + double best_cost; + double global_best_cost; + double average_cost; + double standard_deviation; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + ~Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + }; + +// Population --------------------------------------------------------------------------------- + + provides class Population + { + private: + Rarray<Solution*> _parents; // individuals in population + Rarray<Solution*> _offsprings; // offsprings of current population + Rarray<Solution*> _new_parents; // individuals of previous population + Rarray<struct individual> _fitness_values; + Rarray<struct individual> _fitness_aux; + const SetUpParams& _setup; + unsigned int _upper_cost,_lower_cost; // lower and upper fitness of individuals in population + unsigned int _evaluations; + double _average_cost; + + public: + inline void Evaluate(Solution *s, struct individual & _f); + + Population(const Problem& pbm,const SetUpParams& setup); // crea un array de objetos population; + ~Population(); + + friend ostream& operator<< (ostream& os, const Population& population); + friend istream& operator>> (istream& is, Population& population); + Population& operator= (const Population& pop); + const SetUpParams& setup() const; + const Problem& pbm() const; + void initialize(); + + // Generate a new pool of individuals in population + void evolution(); + + // interchange solutions between island + void interchange(const unsigned long current_generation, NetStream& channel); + + // creates a array with fitness of all individuals in population and its position in the population + void evaluate_parents(); + + // creates a array with fitness of all individuals and offsprings in population and its position in the population + void evaluate_offsprings(); + + // selects parents to creates offsprings + void select_parents(); + + // selects individuals for the new population + void select_offsprings(); + + const Rarray<Solution*>& parents() const; + const Rarray<Solution*>& offsprings() const; + Rarray<struct individual>& fitness_values(); + + unsigned int upper_cost() const; + unsigned int lower_cost() const; + unsigned int evaluations() const; + Solution& solution(const unsigned int index) const; + double fitness(const unsigned int index) const; + + double best_cost() const; + double worst_cost() const; + Solution& best_solution() const; + Solution& worst_solution() const; + double average_cost() const; + double standard_deviation() const; + }; + +// Inter_Operator ( abstract )----------------------------------------------------------- + + provides class Inter_Operator + { + protected: + unsigned int migration_rate; + unsigned int migration_size; + unsigned int migration_selection_1; + unsigned int migration_selection_2; + unsigned int migration_selection_conf_1; + unsigned int migration_selection_conf_2; + + unsigned int _number_operator; + const Direction direction; + + public: + Inter_Operator(const unsigned int _number_op, const Direction dir); + virtual ~Inter_Operator(); + + friend ostream& operator<< (ostream& os, const Inter_Operator& inter); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const=0; + virtual void setup(char line[MAX_BUFFER]); + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Migration: public Inter_Operator ----------------------------------------------------------- + + provides class Migration: public Inter_Operator + { + public: + Migration(const Direction dir); + virtual ~Migration(); + + friend ostream& operator<< (ostream& os, const Migration& migration); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const; + }; + +// Selection --------------------------------------------------------- + + provides class Selection + { + protected: + unsigned int _number_selection; + const Direction direction; + + public: + + Selection(const Direction dir); + Selection(const unsigned int _number_sel, const Direction dir); + virtual ~Selection(); + + friend ostream& operator<< (ostream& os, const Selection& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + unsigned int number_selection() const; + + virtual void setup(char line[MAX_BUFFER]); + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + + }; + +// Selection_Parents --------------------------------------------------------------------------------- + + provides class Selection_Parents: public Selection + { + private: + mutable unsigned int selection_position; + + public: + Selection_Parents(const Direction dir); + virtual ~Selection_Parents(); + + friend ostream& operator<< (ostream& os, const Selection_Parents& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const; + }; + +// Selection_New_Population --------------------------------------------------------------------------- + + provides class Selection_New_Population: public Selection + { + private: + mutable unsigned int selection_position; + mutable int d; + Intra_Operator *diverge; + float r; + + public: + Selection_New_Population(const Direction dir); + virtual ~Selection_New_Population(); + + friend ostream& operator<< (ostream& os, const Selection_New_Population& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const; + + virtual void setup(char line[MAX_BUFFER]); + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Selection_Tournament --------------------------------------------------------------------------------- + + provides class Selection_Tournament: public Selection + { + public: + Selection_Tournament(const Direction dir); + virtual ~Selection_Tournament(); + + friend ostream& operator<< (ostream& os, const Selection_Tournament& sel); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tourment_size,const bool remplace) const; + }; + +// Selection_Roulette_Wheel --------------------------------------------------------------------------------- + + provides class Selection_Roulette_Wheel: public Selection + { + public: + Selection_Roulette_Wheel(const Direction); + virtual ~Selection_Roulette_Wheel(); + + friend ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + }; + +// Selection_Rank --------------------------------------------------------------------------------- + + provides class Selection_Rank: public Selection + { + public: + Selection_Rank(const Direction dir); + Selection_Rank(const unsigned int _number_sel, const Direction dir); + virtual ~Selection_Rank(); + + friend ostream& operator<< (ostream& os, const Selection_Rank& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual void reset(); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const; + }; + +// Selection_Best --------------------------------------------------------------------------------- + + provides class Selection_Best: public Selection_Rank + { + private: + mutable unsigned int selection_best_position; + + public: + Selection_Best(const Direction); + virtual ~Selection_Best(); + + friend ostream& operator<< (ostream& os, const Selection_Best& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Selection_Worst --------------------------------------------------------------------------------- + + provides class Selection_Worst: public Selection_Rank + { + private: + mutable unsigned int selection_worst_position; + + public: + Selection_Worst(const Direction); + virtual ~Selection_Worst(); + + friend ostream& operator<< (ostream& os, const Selection_Worst& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Operator_Pool ------------------------------------------------------------------------- + + // pool with all operators and selections that can be chosen in the setup file + provides class Operator_Pool + { + private: + mutable Rlist<Intra_Operator> _intra_operators; + Rlist<Selection> _selectors; + Rlist<Inter_Operator> _inter_operators; + + public: + Operator_Pool(const Problem& pbm); + ~Operator_Pool(); + + Intra_Operator& intra_operator(const unsigned int index) const; + Rlist<Intra_Operator>& intra_operators() const; + Selection& selector(const unsigned int index) const; + const Rlist<Selection>& selectors() const; + Inter_Operator& inter_operator(const unsigned int index) const; + const Rlist<Inter_Operator>& inter_operators() const; + + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Population current_population; + StateCenter _sc; + + double best_cost; + double worst_cost; + Solution best_solution; + double average_cost; + double standard_deviation; + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_evaluations; + + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_worst_cost; + State_Vble _current_average_cost; + State_Vble _current_standard_deviation; + State_Vble _current_time_spent; + + State_Vble _best_solution_trial; + State_Vble _best_cost_trial; + State_Vble _worst_cost_trial; + State_Vble _iteration_best_found_in_trial; + State_Vble _evaluations_best_found_in_trial; + State_Vble _time_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _evaluations_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _global_worst_cost; + State_Vble _time_best_found; + + State_Vble _crossover_probability; // probability of applying the operator over population + State_Vble _diverge_probability; // probability of applying the operator over population + State_Vble _user_op_probability[MAX_USER_OP]; // probabilities of user operators + State_Vble _migration_rate; + State_Vble _migration_size; + State_Vble _migration_selection_1; + State_Vble _migration_selection_2; + State_Vble _migration_selection_conf_1; + State_Vble _migration_selection_conf_2; + State_Vble _select_parents; + State_Vble _select_offsprings; + State_Vble _parameter_select_new_pop; + + State_Vble _display_state; + + public: + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + + virtual int pid() const; + bool end_trial() const; + void end_trial(bool et); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (const unsigned long int nb_generations) =0; + virtual void run (const Population& pop,const unsigned long int nb_generations) =0; + + //Partial execution + virtual void StartUp()=0; + virtual void StartUp(const Population& pop)=0; + + virtual void DoStep()=0; + + // Statistics handling ---------------------------------------------------------------------- + + Statistics& statistics(); + UserStatistics& userstatistics (); + Population& population(); + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling --------------------------------------------------------------------------- + + void RefreshState(); + void RefreshCfgState(); + void UpdateFromState(); + void UpdateFromCfgState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + unsigned long current_evaluations() const; + Solution current_best_solution() const; + double current_best_cost() const; + double current_worst_cost() const; + double current_average_cost() const; + double current_standard_deviation() const; + float current_time_spent() const; + Solution best_solution_trial() const; + double best_cost_trial() const; + double worst_cost_trial() const; + unsigned int iteration_best_found_in_trial() const; + unsigned int evaluations_best_found_in_trial() const; + float time_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + unsigned int evaluations_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + double global_worst_cost() const; + float time_best_found() const; + int display_state() const; + + float *crossover_probability() const; + float *diverge_probability() const; + float *user_op_probability(const int index) const; + unsigned int migration_rate() const; + unsigned int migration_size() const; + unsigned int migration_selection_1() const; + unsigned int migration_selection_2() const; + unsigned int migration_selection_conf_1() const; + unsigned int migration_selection_conf_2() const; + unsigned int select_parents() const; + unsigned int select_offprings() const; + float parameter_select_new_pop() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_evaluations(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_worst_cost(const double value); + void current_average_cost(const double value); + void current_standard_deviation(const double value); + void current_time_spent(const float value); + void best_solution_trial(const Solution& sol); + void best_cost_trial(const double value); + void worst_cost_trial(const double value); + void iteration_best_found_in_trial(const unsigned int value); + void evaluations_best_found_in_trial(const unsigned int value); + void time_best_found_trial(const float value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void evaluations_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void global_worst_cost(const double value); + void time_best_found(const float value); + void display_state(const int value); + + void crossover_probability(const float *probability); + void diverge_probability(const float *probability); + void user_op_probability(const int index,const float *probability); + void migration_rate(const unsigned int rate); + void migration_size(const unsigned int size); + void migration_selection_1(const unsigned int seleciton_1); + void migration_selection_2(const unsigned int selection_2); + void migration_selection_conf_1(const unsigned int selection_conf_1); + void migration_selection_conf_2(const unsigned int selection_conf_2); + void select_parents(const unsigned int selection); + void select_offsprings(const unsigned int selection); + void parameter_select_new_pop(const float value); + + void KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_trial,const float total_time_spent); + + void show_state() const; + }; + + provides class Solver_Seq: public Solver + { + public: + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state(); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + int acum_evaluations; + int acum_iterations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state(); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + int acum_evaluations; + int acum_iterations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + void reset(); + }; + +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.cc new file mode 100644 index 0000000..65672fd --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.cc @@ -0,0 +1,3033 @@ +#include "CHC.hh" + +skeleton CHC +{ +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (Operator_Pool& pool) + : _independent_runs(0), + _nb_evolution_steps(0), + _population_size(0), + _select_parents(6), // Selection of parents: Select all individuals. (fixed) + _select_offsprings(7), // Selection of offspring : Select the best individuals. (fixed) + _inter_operators(), + _intra_operators(), + _refresh_global_state(1), + _synchronized(0), + _check_asynchronous(1), + _display_state(0), + _pool(pool) + {} + + Operator_Pool& SetUpParams::pool() const + { + return _pool; + } + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + long op; + int parameter; + short int nb_section=0; + short int nb_io = 0; + short int nb_param=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"Selection-Parameters"))) nb_section=1; + if (!(strcmp(command,"Intra-Operators"))) nb_section=2; + if (!(strcmp(command,"Inter-Operators"))) nb_section=3; + if (!(strcmp(command,"LAN-configuration"))) nb_section=4; + + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.nb_evolution_steps(op); break; + case 2: setup.population_size(op); break; + case 3: setup.display_state(op); break; + } + nb_param++; + break; + case 1: setup.pool().selector(setup.select_offsprings()).setup(buffer); + break; + case 2: setup.pool().intra_operators().append(Intra_Operator::create(op)); + setup.pool().intra_operator(nb_io).setup(buffer); + setup._intra_operators.append(new unsigned int(nb_io)); + nb_io++; + break; + case 3: setup._inter_operators.append(new unsigned int(op)); + setup.pool().inter_operator(op).setup(buffer); + break; + case 4: if (nb_LAN_param>=3) break; + switch (nb_LAN_param) + { + case 0: setup.refresh_global_state(op); break; + case 1: setup.synchronized(op); break; + case 2: assert(op>0); + setup.check_asynchronous(op); break; + } + nb_LAN_param++; + break; + } + } + + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evolution steps: " << setup.nb_evolution_steps() << endl + << "\t" << "Size of Population: " << setup.population_size() << endl; + os << "\t" <<"With combination between parents and offsprings" << endl; + + os << "\t" << "Display State: " << setup.display_state() << endl << endl + << "\t" << "Selections:" << endl + << "\t" << "-----------" << endl << endl + << "\t" << "Selection parents -> " << setup.pool().selector(setup.select_parents()) << endl + << "\t" << "Selection offsprings -> " << setup.pool().selector(setup.select_offsprings()) << endl + << "\t" << "Intra_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.intra_operators_size();i++) + os << "\t" << (setup.pool().intra_operator(setup.intra_operator_index(i))) << endl; + + os << endl << "\t" << "Inter_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.inter_operators_size();i++) + os << "\t" << "Operator: " << setup.pool().inter_operator(setup.inter_operator_index(i)) << endl; + + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + os << "\t" << "Interval for checking asynchronous receptions: " << setup.check_asynchronous() << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + continue_question(); + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::nb_evolution_steps() const + { + return _nb_evolution_steps; + } + + const unsigned int SetUpParams::population_size() const + { + return _population_size; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::check_asynchronous() const + { + return _check_asynchronous; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs=val; + } + + void SetUpParams::nb_evolution_steps(const unsigned long val) + { + _nb_evolution_steps=val; + } + + void SetUpParams::population_size(const unsigned int val) + { + _population_size=val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::check_asynchronous(const unsigned int val) + { + _check_asynchronous=val; + } + + const unsigned int SetUpParams::select_parents() const + { + return _select_parents; + } + + const unsigned int SetUpParams::select_offsprings() const + { + return _select_offsprings; + } + + void SetUpParams::select_parents(const unsigned int val) + { + _select_parents=val; + } + + void SetUpParams::select_offsprings(const unsigned int val) + { + _select_offsprings=val; + } + + const unsigned int SetUpParams::intra_operator_index(const unsigned int index) const + { + return _intra_operators[index]; + } + + const unsigned int SetUpParams::intra_operators_size() const + { + return _intra_operators.size(); + } + + const unsigned int SetUpParams::inter_operator_index(const unsigned int index) const + { + return _inter_operators[index]; + } + + const unsigned int SetUpParams::inter_operators_size() const + { + return _inter_operators.size(); + } + + void SetUpParams::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_select_parents",(char *)&_select_parents,1,sizeof(_select_parents)); + _sc.set_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,1,sizeof(_select_offsprings)); + _sc.set_contents_state_variable("_display_state",(char *)&_display_state,1,sizeof(bool)); + } + + void SetUpParams::UpdateFromState(const StateCenter& _sc) const + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_select_parents",(char *)&_select_parents,nbytes,length); + _sc.get_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_display_state",(char *)&_display_state,nbytes,length); + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Trial: " << stats.stats_data[i].trial + << " Generation: " << stats.stats_data[i].nb_generation + << " Evaluation: " << stats.stats_data[i].nb_evaluation + << " Current best cost: " << stats.stats_data[i].best_cost + << " Global best cost: " << stats.stats_data[i].global_best_cost + << " Avg: " << stats.stats_data[i].average_cost + << " Std. Dev.: " << stats.stats_data[i].standard_deviation; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + struct stat *new_stat=(struct stat *)malloc(sizeof(struct stat)); + + new_stat->trial=solver.current_trial(); + new_stat->nb_generation=solver.current_iteration(); + new_stat->nb_evaluation=solver.current_evaluations(); + new_stat->average_cost=solver.current_average_cost(); + new_stat->standard_deviation=solver.current_standard_deviation(); + new_stat->best_cost=solver.current_best_cost(); + new_stat->global_best_cost=solver.global_best_cost(); + + stats_data.append(*new_stat); + } + + void Statistics::clear() + { + stats_data.remove(); + } + + Statistics::~Statistics() + {} + +// Population ------------------------------------------------------ + + Population::Population(const Problem& pbm,const SetUpParams& setup) + :_parents(setup.population_size()), + _fitness_values(setup.population_size()), + _new_parents(setup.population_size()), + _offsprings(setup.population_size()), + _setup(setup), + _evaluations(0) + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]=new Solution(pbm); + _new_parents[i]=new Solution(pbm); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + for (int i=0;i<_offsprings.size();i++) + _offsprings[i]=new Solution(pbm); + + } + + void Population::Evaluate(Solution* sols,struct individual &_f) + { + if(_f.change) + { + _f.change = false; + _f.fitness = sols->fitness(); + _evaluations++; + } + } + + Population& Population::operator= (const Population& pop) + { + for (int i=0;i<_parents.size();i++) + { + *_parents[i]=*((pop.parents())[i]); + _fitness_values[i] = pop._fitness_values[i]; + _evaluations = pop._evaluations; + } + return (*this); + } + + istream& operator>> (istream& is, Population& population) + { + return is; + } + + ostream& operator<< (ostream& os, const Population& population) + { + os << "---------------------------------------------------------------" << endl; + os << " PRESENT POPULATION " << endl << endl; + for (int i=0;i<population._parents.size();i++) + os << *population._parents[i] << endl; + os << endl << "---------------------------------------------------------------" << endl; + return os; + } + + const SetUpParams& Population::setup() const + { + return _setup; + } + + void Population::initialize() + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]->initialize(); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + evaluate_parents(); + } + + void Population::evaluate_parents() + { + double upper_fitness=(infinity() * (-1)); + double lower_fitness=(infinity()); + double current_fitness; + double cost=0.0; + + for (int i=0;i<_fitness_values.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + current_fitness = _fitness_values[i].fitness; + + if (current_fitness > upper_fitness ) + { + _upper_cost=i; + upper_fitness = current_fitness; + } + + if (current_fitness < lower_fitness ) + { + _lower_cost=i; + lower_fitness = current_fitness; + } + + cost += current_fitness; + } + + _average_cost = cost / _fitness_values.size(); + } + + void Population::evaluate_offsprings() + { + int i=0; + + _fitness_aux=Rarray<struct individual>(_parents.size() + _offsprings.size()); + for (i=0;i<_parents.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + _fitness_aux[i] = _fitness_values[i]; + } + + for (int j=i;(j-i)<_offsprings.size();j++) + { + _fitness_aux[j].index=j; + _fitness_aux[j].change=true; + Evaluate(_offsprings[j-i],_fitness_aux[j]); + } + } + + void Population::evolution() + { + select_parents(); // selects individuals to apply operators + + // apply selected operators + for (int i=0;i<_setup.intra_operators_size();i++) + _setup.pool().intra_operator(_setup.intra_operator_index(i)).execute(_offsprings); + + evaluate_offsprings(); + select_offsprings(); // selects new individuals + evaluate_parents(); // calculates fitness of new individuals + } + + void Population::interchange(const unsigned long current_generation, NetStream& channel) + { + // apply selected operators + for (int i=0;i<_setup.inter_operators_size();i++) + _setup.pool().inter_operator(_setup.inter_operator_index(i)).execute((*this),current_generation,channel,_setup.synchronized(),_setup.check_asynchronous()); + } + + void Population::select_parents() + { + _setup.pool().selector(_setup.select_parents()).prepare(_fitness_values,false); + struct individual ind; + for (int i=0;i<_offsprings.size();i++) + { + ind = _setup.pool().selector(_setup.select_parents()).select_one(_parents,_offsprings,_fitness_values,0,false); + *_offsprings[i] = *_parents[ind.index]; + } + } + + void Population::select_offsprings() + { + _setup.pool().selector(_setup.select_offsprings()).prepare(_fitness_aux,false); + const int ps = _parents.size(); + Rarray<struct individual> aux(ps); + + for (int i=0;i<ps;i++) + { + aux[i] = _setup.pool().selector(_setup.select_offsprings()).select_one(_parents,_offsprings,_fitness_aux,0,false); + if(aux[i].index < ps) + { + *_new_parents[i] = *_parents[aux[i].index]; + aux[i].index = i; + } + else + { + *_new_parents[i] = *_offsprings[aux[i].index-ps]; + aux[i].index = i; + } + } + + Solution *interchange; + for (int i=0;i<ps;i++) + { + interchange=_parents[i]; + _parents[i]=_new_parents[i]; // interchanges pointers to solutions ( NO solutions !! ) + _new_parents[i]=interchange; + } + + for (int i=0;i<ps;i++) + { + _fitness_values[i] = aux[i]; + } + } + + const Rarray<Solution*>& Population::parents() const + { + return _parents; + } + + const Rarray<Solution*>& Population::offsprings() const + { + return _offsprings; + } + + Rarray<struct individual>& Population::fitness_values() + { + return _fitness_values; + } + + unsigned int Population::upper_cost() const + { + return _upper_cost; + } + + unsigned int Population::lower_cost() const + { + return _lower_cost; + } + + unsigned int Population::evaluations() const + { + return _evaluations; + } + + double Population::best_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_lower_cost].fitness; + else + return _fitness_values[_upper_cost].fitness; + } + + double Population::worst_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_upper_cost].fitness; + else + return _fitness_values[_lower_cost].fitness; + } + + Solution& Population::best_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_lower_cost].index]; + else + return *_parents[_fitness_values[_upper_cost].index]; + } + + Solution& Population::worst_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_upper_cost].index]; + else + return *_parents[_fitness_values[_lower_cost].index]; + } + + Solution& Population::solution(const unsigned int index) const + { + return *_parents[index]; + } + + double Population::fitness(const unsigned int index) const + { + return _fitness_values[index].fitness; + } + + double Population::average_cost() const + { + return _average_cost; + } + + double Population::standard_deviation() const + { + double standard=0.0; + for (int i=0;i<_fitness_values.size();i++) + standard += pow ((_fitness_values[i].fitness - _average_cost),2); + standard=sqrt(standard / (_fitness_values.size()-1)); + return standard; + } + + Population::~Population() + { + for (int i=0;i<_parents.size();i++) + delete(_parents[i]); + for (int i=0;i<_offsprings.size();i++) + delete(_offsprings[i]); + for (int j=0;j<_new_parents.size();j++) + delete(_new_parents[j]); + } + +// Intra_operator -------------------------------------------------------------- + + Intra_Operator::Intra_Operator(const unsigned int _number_op):_number_operator(_number_op),probability(NULL) + {} + + unsigned int Intra_Operator::number_operator() const + { + return _number_operator; + } + + Intra_Operator *Intra_Operator::create(unsigned int _number_op) + { + switch (_number_op) + { + case 0: return new Crossover();break; + case 1: return new Diverge();break; + default: return User_Operator::create(_number_op); break; + } + } + + ostream& operator<< (ostream& os, const Intra_Operator& intra) + { + switch (intra.number_operator()) + { + case 0: os << (Crossover&)intra;break; + case 1: os << (Diverge&)intra;break; + default: os << (User_Operator&)intra;break; + } + return os; + } + + Intra_Operator::~Intra_Operator() + {} + +// Crossover:Intra_operator ------------------------------------------------------------- + + Crossover::Crossover():Intra_Operator(0) + { + probability = new float[1]; + probability[0] = -1.0; + } + + void Crossover::cross(Solution& sol1,Solution& sol2) const // dadas dos soluciones de la poblacion, las cruza + { + int dh = 0; + + if(probability[0] <= 0.0) + { + probability[0] = sol1.lengthInBits()/4; + } + + for(int i = 0; i < sol1.lengthInBits();i++) + if(!sol1.equalb(i,sol2)) dh++; + + if((dh/2) > probability[0]) + { + for(int i = 0; i < sol1.lengthInBits();i++) + if((!sol1.equalb(i,sol2)) && (0.5 <= rand01())) + { + sol1.swap(i,sol2); + } + } + else + { + sol1.invalid(); + sol2.invalid(); + } + } + + void Crossover::execute(Rarray<Solution*>& sols) const + { + for(int i=0;i+1<sols.size();i=i+2) + cross(*sols[i],*sols[i+1]); + } + + ostream& operator<< (ostream& os, const Crossover& cross) + { + os << "Crossover."; + return os; + } + + void Crossover::RefreshState(const StateCenter& _sc) const + {} + + void Crossover::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)probability,nbytes,length); + } + + void Crossover::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d ",&op); + } + + Crossover::~Crossover() + { + delete [] probability; + } + + +// Diverge: Sub_operator ------------------------------------------------------------- + + Diverge::Diverge():Intra_Operator(1) + { + probability = new float[1]; + } + + void Diverge::diverge(Solution& sol) const + { + for(int i = 0; i < sol.lengthInBits(); i++) + if(rand01() < probability[0]) sol.flip(i); + } + + void Diverge::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i<sols.size();i++) + diverge(*sols[i]); + } + + ostream& operator<< (ostream& os, const Diverge& diverge) + { + os << "Diverge." << " Probability: " << diverge.probability[0]; + return os; + } + + void Diverge::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f ",&op,&probability[0]); + assert(probability[0]>=0); + } + + void Diverge::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_diverge_probability",(char *)probability,1,sizeof(float)); + } + + void Diverge::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_diverge_probability",(char *)probability,nbytes,length); + } + + Diverge::~Diverge() + { + delete [] probability; + } + + +// Inter_operator ------------------------------------------------------------------- + + Inter_Operator::Inter_Operator(const unsigned int _number_op,const Direction dir): + _number_operator(_number_op), + direction(dir), + migration_rate(1), + migration_size(1), + migration_selection_1(0), + migration_selection_2(0), + migration_selection_conf_1(0), + migration_selection_conf_2(0) + {} + + unsigned int Inter_Operator::number_operator() const + { + return _number_operator; + } + + void Inter_Operator::setup(char line[MAX_BUFFER]) + { + int op; + int new_migration_rate=1; + int new_migration_size=1; + int new_migration_selection_1=0; + int new_migration_selection_conf_1=0; + int new_migration_selection_2=0; + int new_migration_selection_conf_2=0; + + sscanf(line," %d %d %d %d %d %d %d ",&op,&new_migration_rate,&new_migration_size,&new_migration_selection_1,&new_migration_selection_conf_1,&new_migration_selection_2,&new_migration_selection_conf_2); + + assert(new_migration_rate>0); + assert(new_migration_size>0); + assert(new_migration_selection_1>=0); + assert(new_migration_selection_conf_1>=0); + assert(new_migration_selection_2>=0); + assert(new_migration_selection_conf_2>=0); + + migration_rate=new_migration_rate; + migration_size=new_migration_size; + migration_selection_1=new_migration_selection_1; + migration_selection_conf_1=new_migration_selection_conf_1; + migration_selection_2=new_migration_selection_2; + migration_selection_conf_2=new_migration_selection_conf_2; + } + + void Inter_Operator::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_migration_rate",(char *)&migration_rate,1,sizeof(migration_rate)); + _sc.set_contents_state_variable("_migration_size",(char *)&migration_size,1,sizeof(migration_size)); + _sc.set_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,1,sizeof(migration_selection_1)); + _sc.set_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,1,sizeof(migration_selection_2)); + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,1,sizeof(migration_selection_conf_1)); + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,1,sizeof(migration_selection_conf_2)); + } + + void Inter_Operator::UpdateFromState(const StateCenter& _sc) + { + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&migration_rate,nitems,length); + _sc.get_contents_state_variable("_migration_size",(char *)&migration_size,nitems,length); + _sc.get_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,nitems,length); + } + + ostream& operator<< (ostream& os, const Inter_Operator& inter) + { + switch (inter.number_operator()) + { + case 0: os << (Migration&)inter;break; + } + return os; + } + + Inter_Operator::~Inter_Operator() + {} + +// Migration ------------------------------------------------------------ + + Migration::Migration(const Direction dir):Inter_Operator(0,dir) + {} + + void Migration::execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asynchronous) const + { + + Solution* solution_to_send; + Solution* solution_received; + Solution* solution_to_remplace; + bool need_to_revaluate=false; + int mypid; + + int nb_proc=_netstream.pnumber(); // Get the number of processes running + + mypid=_netstream.my_pid(); + + int to = (mypid + 1) % nb_proc; // Source (from) and Target (to) of processes + int from = (nb_proc + mypid - 1) % nb_proc; + + // process number 0 is only to store the global state + if (to==0) to=1; + if (from==0) from=nb_proc - 1; + + _netstream << set_target(to) << set_source(from) + << get_target(&to) << get_source(&from); + + if ( (current_generation % migration_rate) == 0 + && (current_generation!=pop.setup().nb_evolution_steps())) // in this generation this operator have to be applied + { + pop.setup().pool().selector(migration_selection_1).prepare(pop.fitness_values(),false); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to send + solution_to_send = pop.parents()[pop.setup().pool().selector(migration_selection_1).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_1,false).index]; + + _netstream << *solution_to_send; + } + _netstream << pack_end; + + if (synchronized) // synchronous mode: blocked until data are received + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << set_source(MPI_ANY_SOURCE); + int tipo = 0; + _netstream._wait2(any,tipo); + + if (tipo == 1){ + return; + } + + _netstream << wait(packed); + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } + _netstream << pack_end; + + } + } // end if + + if (!synchronized && ((current_generation % check_asynchronous) ==0)) + { // asynchronous mode: if there are not data, continue; + // but, if there are data, i have to receive it + int pending=false; + _netstream._probe(packed,pending); + if (pending) + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + pending=false; + _netstream._probe(regular,pending); + if (!pending) break; + + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } // end for + _netstream << pack_begin; + } // end if + } + + if (need_to_revaluate) pop.evaluate_parents(); + } + + ostream& operator<< (ostream& os, const Migration& migration) + { + os << "Migration." + << endl << "\t" << " Rate: " << migration.migration_rate + << endl << "\t" << " Size: " << migration.migration_size + << endl << "\t" << " Selection 1: " << migration.migration_selection_1 + << endl << "\t" << " Selection 1 Parameter: " << migration.migration_selection_conf_1 + << endl << "\t" << " Selection 2: " << migration.migration_selection_2 + << endl << "\t" << " Selection 2 Parameter: " << migration.migration_selection_conf_2; + return os; + } + + Migration::~Migration() + {} + +// Selection ------------------------------------------------------------ + + Selection::Selection(const Direction dir):_number_selection(0),direction(dir) + {} + + Selection::Selection(const unsigned int _number_sel, const Direction dir):_number_selection(_number_sel),direction(dir) + {} + + void Selection::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + {} + + struct individual Selection::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const + { // select a random individual + return fitness_values[rand_int(0,fitness_values.size()-1)]; + } + + unsigned int Selection::number_selection() const + { + return _number_selection; + } + + ostream& operator<< (ostream& os, const Selection& sel) + { + switch (sel.number_selection()) + { + case 0: os << "Random Selection"; break; + case 1: os << (Selection_Tournament&)sel; break; + case 2: os << (Selection_Roulette_Wheel&)sel; break; + case 3: os << (Selection_Rank&)sel; break; + case 4: os << (Selection_Best&)sel; break; + case 5: os << (Selection_Worst&)sel; break; + case 6: os << (Selection_Parents&)sel; break; + case 7: os << (Selection_New_Population&)sel; break; + } + return os; + } + + void Selection::setup(char line[MAX_BUFFER]) + {} + + void Selection::RefreshState(const StateCenter& _sc) const + {} + + void Selection::UpdateFromState(const StateCenter& _sc) + {} + + + Selection::~Selection() + {} + +// Selection_Tournament---------------------------------------------------- + + Selection_Tournament::Selection_Tournament(const Direction dir):Selection(1,dir) + {} + + struct individual Selection_Tournament::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tournament_size, const bool remplace) const + { + unsigned int best_sol=0; + double best_fitness=((-1) * direction * infinity()); + unsigned int index; + + if (remplace) best_fitness = -1 * best_fitness; + + unsigned int new_tournament_size=tournament_size; + if (tournament_size==0) new_tournament_size=1; + + for (int i=0;i<new_tournament_size;i++) + { + index=rand_int(0,fitness_values.size()-1); + + switch (direction) + { + case (minimize): if (((!remplace) && (fitness_values[index].fitness<best_fitness)) + || ((remplace) && (fitness_values[index].fitness>best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + case (maximize): if (((!remplace) && (fitness_values[index].fitness>best_fitness)) + || ((remplace) && (fitness_values[index].fitness<best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + } + } + + return fitness_values[best_sol]; + } + + ostream& operator<< (ostream& os, const Selection_Tournament& sel) + { + os << "Tournament Selection."; + return os; + } + + Selection_Tournament::~Selection_Tournament() + {} + +// Selection_Roulette_Wheel --------------------------------------------------- + + Selection_Roulette_Wheel::Selection_Roulette_Wheel(const Direction dir):Selection(2,dir) + {} + + void Selection_Roulette_Wheel::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + + double overall_fitness=0.0; + + // inverts fitness values to select less fitness individuals with a high probability + if ((direction==maximize && (remplace)) || ((direction==minimize) && (!(remplace)))) + { + // fitness assigned if the fitness value is 0 in this case + double value_if_zero=DBL_MAX; + unsigned int nb_zeros=0; + + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + value_if_zero-=fitness_values[i].fitness; + else + nb_zeros++; + } + + value_if_zero=value_if_zero/nb_zeros; + + // Warning !! if fitness is 0 (1/0 ?) + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + fitness_values[i].sel_parameter = (1 / fitness_values[i].fitness ); + else + fitness_values[i].sel_parameter = value_if_zero; + overall_fitness+= fitness_values[i].sel_parameter; + } + } + else + { + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = fitness_values[i].fitness; + overall_fitness+= fitness_values[i].sel_parameter; + } + + } + + if (overall_fitness>DBL_MAX) overall_fitness=DBL_MAX; + + // calculate relative fitness + double previous=0.0; + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = (fitness_values[i].sel_parameter / overall_fitness) + previous; + previous = fitness_values[i].sel_parameter; + } + } + + struct individual Selection_Roulette_Wheel::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy, const bool remplace) const + { + double random_selected=rand01(); + int i=0; + + while (random_selected > fitness_values[i].sel_parameter ) + i++; + + return fitness_values[i]; + } + + ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel) + { + os << "Roulette Wheel Selection."; + return os; + } + + Selection_Roulette_Wheel::~Selection_Roulette_Wheel() + {} + +// Selection_Rank -------------------------------------------------- + + int lessF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness < i2.fitness; + } + + int greaterF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness > i2.fitness; + } + + Selection_Rank::Selection_Rank(const Direction dir):Selection(3,dir) + {} + + Selection_Rank::Selection_Rank(const unsigned int _number_sel, const Direction dir):Selection(_number_sel,dir) + {} + + void Selection_Rank::reset() + {} + + void Selection_Rank::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + reset(); + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(lessF); + else + fitness_values.sort(greaterF); + } + + struct individual Selection_Rank::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const + { + + unsigned int new_portion=portion; + if (portion==0 || portion>100) new_portion=100; + + return fitness_values[rand_int(0,(( fitness_values.size() * new_portion )/ 100)-1)]; + } + + ostream& operator<< (ostream& os, const Selection_Rank& sel) + { + os << "Rank-Ordered Selection."; + return os; + } + + Selection_Rank::~Selection_Rank() + {} + +// Selection_Best -------------------------------------------------- + + Selection_Best::Selection_Best(const Direction dir):Selection_Rank(4,dir),selection_best_position(0) + {} + + struct individual Selection_Best::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_best_position; + selection_best_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + return fitness_values[position_to_return]; + } + + void Selection_Best::reset() + { + selection_best_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Best& sel) + { + os << "Selection of best ordered individuals."; + return os; + } + + Selection_Best::~Selection_Best() + {} + +// Selection_Worst -------------------------------------------------- + + Selection_Worst::Selection_Worst(const Direction dir):Selection_Rank(5,dir),selection_worst_position(0) + {} + + struct individual Selection_Worst::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_worst_position; + selection_worst_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + int index=(fitness_values.size()-1) - position_to_return; + return fitness_values[index]; + } + + void Selection_Worst::reset() + { + selection_worst_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Worst& sel) + { + os << "Selection of worst ordered individuals."; + return os; + } + + Selection_Worst::~Selection_Worst() + {} + +// Selection_Parents --------------------------------------------------------------------------------- + + Selection_Parents::Selection_Parents(const Direction dir):Selection(6,dir),selection_position(0) + {} + + Selection_Parents::~Selection_Parents() + {} + + ostream& operator<< (ostream& os, const Selection_Parents& sel) + { + os << "CHC Selection: Parents Selection."; + return os; + } + + void Selection_Parents::prepare(Rarray<struct individual>& fitness_values,const bool remplace) // const + { + selection_position = 0; + int limit1,limit2; + register int max = fitness_values.size(); + + struct individual interchange; + + for (int i=0;i<max*3;i++) + { + limit1 = rand_int(0,max-1); + limit2 = rand_int(0,max-1); + interchange=fitness_values[limit1]; + fitness_values[limit1]=fitness_values[limit2]; + fitness_values[limit2]=interchange; + } + } + + struct individual Selection_Parents::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const + { + int index = selection_position; + selection_position++; + + index = index % fitness_values.size(); + + return fitness_values[index]; + } + +// Selection_New_Population --------------------------------------------------------------------------- + + Selection_New_Population::Selection_New_Population(const Direction dir) + :Selection(7,dir) + ,diverge(NULL) + ,d(-1) + {} + + Selection_New_Population::~Selection_New_Population() + { + if(diverge != NULL) delete diverge; + } + + ostream& operator<< (ostream& os, const Selection_New_Population& sel) + { + os << "CHC Selection: New Population Selection." << " Diverge Operator: " << *sel.diverge; + return os; + } + + + void Selection_New_Population::prepare(Rarray<struct individual>& fitness_values,const bool remplace) // const + { + selection_position = 0; + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(greaterF); + else + fitness_values.sort(lessF); + } + + struct individual Selection_New_Population::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const + { + bool change = false; + if(d == -1) d = to_select_1[0]->lengthInBits() / 4; + + if(selection_position == 0) + { + for(int i= 0; i < to_select_1.size(); i++) + if(fitness_values[i].index > (to_select_1.size()-1)) change = true; + if(change) selection_position++; + else selection_position--; + } + + if(selection_position == -1) + { + d--; + if(d < 0) + { + selection_position--; + d = (int) (r * (1.0-r) * to_select_1[0]->lengthInBits()); + } + else selection_position = 1; + } + + if(selection_position == -2) + { + assert(diverge != NULL); + for(int i = 1; i < to_select_1.size(); i++) + { + if(rand01() < r) ((Diverge *)diverge)->diverge(*to_select_1[i]); + } + for(int i= 0; i < fitness_values.size(); i++) + if(fitness_values[i].index < (to_select_1.size()-1)) fitness_values[i].change = true; + + selection_position = 1; + } + + if(selection_position > 0) + { + int index = selection_position-1; + selection_position++; + return fitness_values[index]; + } + } + + void Selection_New_Population::setup(char line[MAX_BUFFER]) + { + int div; + float div_par; + + sscanf(line," %f %d %f ",&r,&div, &div_par); + assert(r>=0); + + sprintf(line,"%d %f ",div,div_par); + + diverge = Intra_Operator::create(div); + assert(diverge != NULL); + + diverge->setup(line); + } + + void Selection_New_Population::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_parameter_select_new_pop",(char *)&r,1,sizeof(float)); + } + + void Selection_New_Population::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)&r,nbytes,length); + } + +// Operator_Pool ------------------------------------------------------------------------ + + Operator_Pool::Operator_Pool(const Problem& pbm) + { + // introduces all operators and selections in lists + + // Index to be chosen in setup file + //------------------------------------- + // The Intra_Operators are introduced dimanicly in setup + + _selectors.append(new Selection(pbm.direction())); // 0 + _selectors.append(new Selection_Tournament(pbm.direction())); // 1 + _selectors.append(new Selection_Roulette_Wheel(pbm.direction())); // 2 + _selectors.append(new Selection_Rank(pbm.direction())); // 3 + _selectors.append(new Selection_Best(pbm.direction())); // 4 + _selectors.append(new Selection_Worst(pbm.direction())); // 5 + _selectors.append(new Selection_Parents(pbm.direction())); // 6 + _selectors.append(new Selection_New_Population(pbm.direction())); // 7 + + _inter_operators.append(new Migration(pbm.direction())); // 0 + } + + Intra_Operator& Operator_Pool::intra_operator(const unsigned int index) const + { + assert(index < _intra_operators.size()); + return _intra_operators[index]; + } + + Rlist<Intra_Operator>& Operator_Pool::intra_operators() const + { + return _intra_operators; + } + + Selection& Operator_Pool::selector(const unsigned int index) const + { + assert(index < _selectors.size()); + return _selectors[index]; + } + + const Rlist<Selection>& Operator_Pool::selectors() const + { + return _selectors; + } + + Inter_Operator& Operator_Pool::inter_operator(const unsigned int index) const + { + assert(index < _inter_operators.size()); + return _inter_operators[index]; + } + + const Rlist<Inter_Operator>& Operator_Pool::inter_operators() const + { + return _inter_operators; + } + + Operator_Pool::~Operator_Pool() + {} + +// Solver (superclasse)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + current_population(pbm,setup), + best_cost((-1) * pbm.direction() * infinity()), + worst_cost((-1) * best_cost), + best_solution(problem), + average_cost(0.0), + standard_deviation(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_evaluations("_current_evaluations",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_worst_cost("_current_worst_cost",_sc), + _current_average_cost("_current_average_cost",_sc), + _current_standard_deviation("_current_standard_deviation",_sc), + _current_time_spent("_current_time_spent",_sc), + _best_solution_trial("_best_sol_trial",_sc), + _best_cost_trial("_best_cost_trial",_sc), + _worst_cost_trial("_worst_cost_trial",_sc), + _iteration_best_found_in_trial("_iteration_best_found_in_trial",_sc), + _evaluations_best_found_in_trial("_evaluations_best_found_in_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found",_sc), + _evaluations_best_found("_evaluations_best_found",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _global_worst_cost("_global_worst_cost",_sc), + _time_best_found("_time_best_found",_sc), + _crossover_probability("_crossover_probability",_sc), + _diverge_probability("_diverge_probability",_sc), + _migration_rate("_migration_rate",_sc), + _migration_size("_migration_size",_sc), + _migration_selection_1("_migration_selection_1",_sc), + _migration_selection_2("_migration_selection_2",_sc), + _migration_selection_conf_1("_migration_selection_conf_1",_sc), + _migration_selection_conf_2("_migration_selection_conf_2",_sc), + _select_parents("_select_parents",_sc), + _select_offsprings("_select_offsprings",_sc), + _parameter_select_new_pop("_parameter_select_new_pop",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_evaluations(0); + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + best_solution_trial(best_solution); + best_cost_trial(best_cost); + worst_cost_trial(worst_cost); + iteration_best_found_in_trial(0); + evaluations_best_found_in_trial(0); + time_best_found_trial(time_spent_in_trial); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + evaluations_best_found(0); + global_best_solution(best_solution); + global_best_cost(best_cost); + global_worst_cost(worst_cost); + time_best_found(total_time_spent); + + float prob[MAX_PROB_PER_OP] = {0.0}; + crossover_probability(prob); + diverge_probability(prob); + + char aux[] = "_user_op_probability"; + char nombre[30]; + for(int i = 0; i < MAX_USER_OP; i++) + { + sprintf(nombre,"%s%d",aux,i); + _user_op_probability[i].set_name((char *)nombre); + _sc.add(_user_op_probability[i]); + user_op_probability(i,prob); + } + + migration_rate(0); + migration_size(0); + migration_selection_1(0); + migration_selection_2(0); + migration_selection_conf_1(0); + migration_selection_conf_2(0); + select_parents(0); + select_offsprings(0); + parameter_select_new_pop(0.0); + display_state(setup.display_state()); + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + void Solver::end_trial(bool et) + { + _end_trial = et; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _current_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_iteration.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_evaluations() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_evaluations.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _current_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_average_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_average_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_standard_deviation() const + { + double value=0.0; + unsigned long nitems,length; + _current_standard_deviation.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::best_solution_trial() const + { + Solution sol(problem); + char data_stored[_best_solution_trial.get_nitems() + _best_solution_trial.get_length()]; + unsigned long nitems,length; + _best_solution_trial.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::best_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _best_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::worst_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _worst_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _global_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::global_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _display_state.get_contents((char *)&value, nitems, length); + return value; + } + + float *Solver::crossover_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::diverge_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_diverge_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::user_op_probability(const int index) const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.get_contents_state_variable(aux,(char *)¤t_probability,nitems,length); + return current_probability; + } + + unsigned int Solver::migration_rate() const + { + unsigned int rate=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&rate,nitems,length); + return rate; + } + + unsigned int Solver::migration_size() const + { + unsigned int size=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_size",(char *)&size,nitems,length); + return size; + } + + unsigned int Solver::migration_selection_1() const + { + unsigned int selection_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_1",(char *)&selection_1,nitems,length); + return selection_1; + } + + unsigned int Solver::migration_selection_2() const + { + unsigned int selection_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_2",(char *)&selection_2,nitems,length); + return selection_2; + } + + unsigned int Solver::migration_selection_conf_1() const + { + unsigned int selection_conf_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,nitems,length); + return selection_conf_1; + } + + unsigned int Solver::migration_selection_conf_2() const + { + unsigned int selection_conf_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,nitems,length); + return selection_conf_2; + } + + unsigned int Solver::select_parents() const + { + unsigned int select_parents=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_parents",(char *)&select_parents,nitems,length); + return select_parents; + } + + unsigned int Solver::select_offprings() const + { + unsigned int select_offsprings=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_offsprings",(char *)&select_offsprings,nitems,length); + return select_offsprings; + } + + float Solver::parameter_select_new_pop() const + { + float parameter_select_new_pop; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)¶meter_select_new_pop,nitems,length); + return parameter_select_new_pop; + } + + void Solver::current_trial(const unsigned int value) + { + _current_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _current_iteration.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_evaluations(const unsigned long value) + { + _current_evaluations.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _current_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _current_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_worst_cost(const double value) + { + _current_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_average_cost(const double value) + { + _current_average_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_standard_deviation(const double value) + { + _current_standard_deviation.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::best_solution_trial(const Solution& sol) + { + _best_solution_trial.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::best_cost_trial(const double value) + { + _best_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::worst_cost_trial(const double value) + { + _worst_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::iteration_best_found_in_trial(const unsigned int value) + { + _iteration_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found_in_trial(const unsigned int value) + { + _evaluations_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found(const unsigned int value) + { + _evaluations_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _global_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _global_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::global_worst_cost(const double value) + { + _global_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::display_state(const int value) + { + _display_state.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::crossover_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_crossover_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::diverge_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_diverge_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::user_op_probability(const int index, const float *new_probability) + { + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.set_contents_state_variable(aux,(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::migration_rate(const unsigned int rate) + { + _sc.set_contents_state_variable("_migration_rate",(char *)&rate,1,sizeof(int)); + } + + void Solver::migration_size(const unsigned int size) + { + _sc.set_contents_state_variable("_migration_size",(char *)&size,1,sizeof(int)); + } + + void Solver::migration_selection_1(const unsigned int selection_1) + { + _sc.set_contents_state_variable("_migration_selection_1",(char *)&selection_1,1,sizeof(int)); + } + + void Solver::migration_selection_2(const unsigned int selection_2) + { + _sc.set_contents_state_variable("_migration_selection_2",(char *)&selection_2,1,sizeof(int)); + } + + void Solver::migration_selection_conf_1(const unsigned int selection_conf_1) + { + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,1,sizeof(int)); + } + + void Solver::migration_selection_conf_2(const unsigned int selection_conf_2) + { + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,1,sizeof(int)); + } + + void Solver::select_parents(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_parents",(char *)&selection,1,sizeof(int)); + } + + void Solver::select_offsprings(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_offsprings",(char *)&selection,1,sizeof(int)); + } + + void Solver::parameter_select_new_pop(const float value) + { + _sc.set_contents_state_variable("_parameter_select_new_pop",(char *)&value,1,sizeof(float)); + } + + Statistics& Solver::statistics() + { + return _stat; + } + + UserStatistics& Solver::userstatistics() + { + return _userstat; + } + + Population& Solver::population() + { + return current_population; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool worseG=false; + bool betterT=false; + bool worseT=false; + + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost > global_worst_cost()); + betterT = (best_cost < best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost > worst_cost_trial()); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost < global_worst_cost()); + betterT = (best_cost > best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost < worst_cost_trial()); + break; + } + + if (betterT) + { + best_solution_trial(best_sol); + best_cost_trial(best_cost); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_in_trial(current_iteration()); + evaluations_best_found_in_trial(current_evaluations()); + if (betterG) + { + global_best_solution(best_sol); + global_best_cost(best_cost); + time_best_found(time_spent_in_trial); + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + evaluations_best_found(current_evaluations()); + } + } + + if (worseT) + { + worst_cost_trial(worst_cost); + if (worseG) + global_worst_cost(worst_cost); + } + } + + StateCenter *Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::RefreshCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().selectors().size();i++) + params.pool().selector(i).RefreshState(_sc); + params.RefreshState(_sc); + } + + void Solver::UpdateFromState() + { + best_solution=current_best_solution(); + best_cost=current_best_cost(); + worst_cost=current_worst_cost(); + average_cost=current_average_cost(); + standard_deviation=current_standard_deviation(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().selectors().size();i++) + params.pool().selector(i).UpdateFromState(_sc); + params.UpdateFromState(_sc); + } + + void Solver::show_state() const + { + cout << endl << " Current State ---------------------------------------------" << endl; +/* cout << endl << "Selection parents -> " << select_parents(); + cout << endl << "Parameter of selection: " << parameter_select_parents(); + cout << endl << "Selection offsprings -> " << select_offprings(); + cout << endl << "Parameter of selection: " << parameter_select_offsprings() << endl; + cout << endl << "Crossover_probability: " << crossover_probability(); + cout << endl << "Mutation_probability: " << mutation_probability(); + cout << endl << "User_Operator_probability: " << user_op_probability(0); + cout << endl << "Migration_rate: " << migration_rate(); + cout << endl << "Migration_size: " << migration_size(); + cout << endl << "Migration_selection_1: " << migration_selection_1(); + cout << endl << "Migration_selection_conf_1: " << migration_selection_conf_1(); + cout << endl << "Migration_selection_2: " << migration_selection_2(); + cout << endl << "Migration_selection_conf_2: " << migration_selection_conf_2() << endl; +*/ cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current evaluations: " << current_evaluations(); + cout << endl << "Current best cost: " << current_best_cost(); + cout << endl << "Current worst cost: " << current_worst_cost(); + cout << endl << "Current Average cost: " << current_average_cost(); + cout << endl << "Current Standard Deviation: " << current_standard_deviation(); + cout << endl << endl << "Trial: "; + cout << endl << "Best cost trial: " << best_cost_trial(); + cout << endl << "Worst cost trial: " << worst_cost_trial(); + cout << endl << "Iteration best found in trial: " << iteration_best_found_in_trial(); + cout << endl << "Time best found trial: " << time_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << endl << "Global: "; + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Global worst cost: " << global_worst_cost(); + cout << endl << "Trial best found: " << trial_best_found(); + cout << endl << "Iteration best found: " << iteration_best_found(); + cout << endl << "Time best found: " << time_best_found(); +// cout << endl << endl << "Best Solution: " << endl << global_best_solution(); + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + } + +// Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Seq::StartUp(const Population& pop) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + time_best_found_trial(0.0); + + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + UpdateFromCfgState(); + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + if( (current_iteration() % params.refresh_global_state()) == 0) + UpdateFromCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs() ) + run(params.nb_evolution_steps()); + } + + void Solver_Seq::run (const unsigned long int nb_generations) + { + StartUp(); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + void Solver_Seq::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + // Solver LAN ------------------------------------------------------------ + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Lan::StartUp(const Population& pop) + { + _netstream << barrier; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Lan::send_local_state_to(int _mypid) { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_solution_trial() + << current_best_solution() + << best_cost_trial() + << worst_cost_trial() + << time_best_found_trial() + << current_best_cost() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << pack_end; + } + + int Solver_Lan::receive_local_state() { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_solution_trial + >> best_solution + >> _best_cost_trial + >> _worst_cost_trial + >> _time_best_found_in_trial + >> best_cost + >> worst_cost + >> average_cost + >> standard_deviation + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + << pack_end; + return r_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualizaci�n de las estad�sticas // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Lan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Wan::StartUp(const Population& pop) + { + _netstream << barrier; + + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_cost_trial() + << best_solution_trial() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << time_best_found_trial() + << worst_cost_trial() + << current_best_cost() + << current_best_solution() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << pack_end; + } + + int Solver_Wan::receive_local_state() + { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_cost_trial + >> _best_solution_trial + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + >> _time_best_found_in_trial + >> _worst_cost_trial + >> best_cost + >> best_solution + >> worst_cost + >> average_cost + >> standard_deviation + << pack_end; + return r_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Update Stats // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Wan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + + } + _netstream << barrier; + } + +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.pro.o new file mode 100644 index 0000000000000000000000000000000000000000..41f66470a6785a1cd1b0639260dbc9f227f6ad39 GIT binary patch literal 191488 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.cc new file mode 100644 index 0000000..df05c01 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.cc @@ -0,0 +1,332 @@ +#ifndef INC_REQ_CHC +#define INC_REQ_CHC +#include "CHC.hh" +#include <math.h> + +skeleton CHC +{ + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + Problem::~Problem() + {} + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + + double Solution::fitness () const + { + double fitness = 0.0; + + if(_var[0] == 2) return 0.0; + + for (int i=0;i<_var.size();i++) + fitness += _var[i]; + + return fitness; + } + + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + int Solution::lengthInBits() const + { + return _pbm.dimension(); + } + + void Solution::flip(const int index) + { + _var[index] = 1 - _var[index]; + } + + bool Solution::equalb(const int index,Solution &s) + { + return _var[index] == s._var[index]; + } + + void Solution::swap(const int index, Solution &s) + { + int aux = s._var[index]; + s._var[index] = _var[index]; + _var[index] = aux; + } + + void Solution::invalid() + { + _var[0] = 2; + } + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].worst_cost_trial + << "\t\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t\t" << userstat.result_trials[i].nb_iteration_best_found_trial + << "\t\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + void UserStatistics::update(const Solver& solver) + { + if( (solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().nb_evolution_steps()) + && !terminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial = solver.evaluations_best_found_in_trial(); + new_stat->nb_iteration_best_found_trial = solver.iteration_best_found_in_trial(); + new_stat->worst_cost_trial = solver.worst_cost_trial(); + new_stat->best_cost_trial = solver.best_cost_trial(); + new_stat->time_best_found_trial = solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + + // User_Operator:Intra_operator --------------------------------------------------------- + + User_Operator::User_Operator(const unsigned int _number_op):Intra_Operator(_number_op) + {} + + void User_Operator::execute(Rarray<Solution*>& sols) const + {} + + void User_Operator::setup(char line[MAX_BUFFER]) + {} + + Intra_Operator *User_Operator::create(const unsigned int _number_op) + { + return new User_Operator(_number_op); + } + + ostream& operator<< (ostream& os, const User_Operator& u_op) + { + os << "User Operator."; + return os; + } + + void User_Operator::RefreshState(const StateCenter& _sc) const + {} + + void User_Operator::UpdateFromState(const StateCenter& _sc) + {} + + User_Operator::~User_Operator() + {} + + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.best_cost_trial() == pbm.dimension()); + } + + StopCondition_1::~StopCondition_1() + {} + + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool terminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} +#endif + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHC.req.o new file mode 100644 index 0000000000000000000000000000000000000000..5120ba4992fe5f72ea6118d14c689c490b673b40 GIT binary patch literal 25240 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHCstructures.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHCstructures.hh new file mode 100644 index 0000000..70aba85 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/CHCstructures.hh @@ -0,0 +1,29 @@ +#ifndef INC_CHC_mallba_hh +#define INC_CHC_mallba_hh + +#include <iostream> +#include <fstream> +#include <math.h> +#include <limits.h> +#include <float.h> +#include <Rlist.h> +#include <Rarray.h> +#include <Messages.h> +#include <mallba.hh> +#include <States.hh> +#include <random.hh> +#include <time.hh> +#include <netstream.hh> +#include <assert.h> + +using namespace std; + +struct individual // index of a individual in the population and its fitness +{ + int index; + double fitness; + double sel_parameter; + bool change; +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Config.cfg new file mode 100644 index 0000000..b34042e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Config.cfg @@ -0,0 +1,3 @@ +CHC.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.chc.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan new file mode 100644 index 0000000000000000000000000000000000000000..f71c6e405ea5e9ef5a0fe9ad9c3c33807afa6d2a GIT binary patch literal 150656 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%0A{#|8_WyPi?W%6s~sep*?E<?DL`<;BiC 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%0DU33JGmU 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.cc new file mode 100644 index 0000000..279b550 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.cc @@ -0,0 +1,49 @@ +#include <iostream> +#include <fstream> +#include "CHC.hh" + +using namespace std; + +int main (int argc, char** argv) +{ + using skeleton CHC; + char path[MAX_BUFFER] = ""; + + system("clear"); + + strcat(path,argv[1]); + ifstream f(path); + if(!f) show_message(10); + + f.getline(path,MAX_BUFFER,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(path,MAX_BUFFER,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(path,MAX_BUFFER,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainLan.o new file mode 100644 index 0000000000000000000000000000000000000000..719588ecb004d2c7131a859e6905d3a50cbaa302 GIT binary patch literal 8992 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 X!Oz(~-d=9)%Xm|PyoQ}4;%xuFo}{|k literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq new file mode 100644 index 0000000000000000000000000000000000000000..eb6ade233d92ae2f16601f662f46bad816b80747 GIT binary patch literal 150704 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 Qp3#=xO1~%KUVi)k4_$gbC;$Ke literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.cc new file mode 100644 index 0000000..4c291f8 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.cc @@ -0,0 +1,43 @@ +#include <iostream> +#include <fstream> +#include "CHC.hh" + +int main (int argc, char** argv) +{ + using skeleton CHC; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution" << solver.global_best_solution() << endl + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainSeq.o new file mode 100644 index 0000000000000000000000000000000000000000..2f4acd33d6c1a0632a10acbd32adcc384510244b GIT binary patch literal 8624 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 O6(AqTdFYmw=lcKrSUQ9N literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainWan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainWan.cc new file mode 100644 index 0000000..4ee19e5 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/MainWan.cc @@ -0,0 +1,52 @@ +#include "CHC.hh" + +int main (int argc, char** argv) +{ + using skeleton CHC; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Makefile new file mode 100644 index 0000000..3225d38 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/Makefile @@ -0,0 +1,24 @@ +include ../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq *.o *% *~ + +MainSeq: CHC.req.o CHC.pro.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainLan: CHC.req.o CHC.pro.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: CHC.req.o CHC.pro.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -np 10 ./MainLan Config.cfg + +WAN: + $(RUN) -v -p4pg pgfileWan MainWan + +SEQ: + ./MainSeq CHC.cfg ../../ProblemInstances/ONEMAX-instances/onemax10.txt res/sol.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/res/empty.txt b/ProyectoFinal/AlgoritmoGenetico/malva/rep/CHC/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Config.cfg new file mode 100644 index 0000000..ad19d32 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Config.cfg @@ -0,0 +1,3 @@ +newGA.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.newga.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan new file mode 100644 index 0000000000000000000000000000000000000000..4412f1cad77b8b6332c1c698973a12e75d51ddba GIT binary patch literal 172968 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 DN9l&6 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.cc new file mode 100644 index 0000000..494e82e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.cc @@ -0,0 +1,53 @@ +#include "newGA.hh" + +int main (int argc, char** argv) +{ + using skeleton newGA; + + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainLan.o new file mode 100644 index 0000000000000000000000000000000000000000..9385dd20caa64bf3c0a87783a4225bf3b2e79568 GIT binary patch literal 9192 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 H-Tr?8LeLyW literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq new file mode 100644 index 0000000000000000000000000000000000000000..da4383cc2eb7ad38bb626ee134b3475b21c1aae0 GIT binary patch literal 172968 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 U`w*4CS7q{F*kaPle>eaC2j;41P5=M^ literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.cc new file mode 100644 index 0000000..d4a7c14 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.cc @@ -0,0 +1,41 @@ +#include "newGA.hh" + +int main (int argc, char** argv) +{ + using skeleton newGA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution: " << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/MainSeq.o new file mode 100644 index 0000000000000000000000000000000000000000..155133b817cf52480267b552dd709539a640c87c GIT binary patch literal 8632 zcmbuEeQX>@6~O0waeOt+*$GK8aRcjePzRdpo$WY|3BhOkk~{h096p;szc%ah+CF-> zYj)R(6Gf0Hb?GT}Nrgm(+Mq_ICD2q<h>s8z2y#nWga}BeDjy<%D72(%NdIVrjAY*1 zow<8n?*^hg`F3}H^WK{`Z)SIA)?Z9!cGLs{Oh|xjXVsFRjLqCyz3#Cud)PX*#@4;L zTE$XxpTJV;=v$#T?2BVgd2XFun%nHuz8HEFFUF52_9Q-?E?-TIB!)+F<pp7W<gGKS z7_&VbT?jTjvbF|%&OH#x1{q5q+aEd`0_#-ye5$-6Vr#woKxAqKW3>&l&wy%X?t78F zwYF-bt(qxc6>5i9+G-!PJr*O`RQa-9l`6k2w6LYab^~wQZOo_2{Sl`>nYnL7er;F% zDO3K3V|Z*^Bvbyob3OM&WU3AVDE}4wrOFq%>!s(}a}Bc#wiAbE=1xblko8m<oI25n zb84<X5(EBD!|MKsWJl8<Y2xid4>2uvPS4ic4k07`kw#u`MVeB_4vFG&y;iPwDAM{) zLnHX-(Vnkxr=?0T=!~~#tH4k+osB`mLIZ|j5)uo;aKP@5==aZsf;fxRRFim!XIP9! zWiTMUPCQ3m#7Pl9clW)CdlL61?n}t?sbd@L9Ee2oKK9tTcnQ+QdnAUK$HS*#dHyWU z^{Sdvee}X2Pk@u)^7*uI#QnEBR;ltl_wN{H%G{8vap!Ke|Lwo;hWuap`tnh~!|^CO zQi*ig^x!eO72n*sxVQ*|Cpe5>ro3SH{(6Q`j8l3365Js3mtMz6n}ky_IWC<9a_I^l z9z(4Ycz6;IPeV6s$rn|{U=qve#c8XcYuyr)b`&g4HBGo=ENK|J(Jg7yrBT(8^l?cs zCZ<cOW|>k!ldMTqQfJh>Z7SuJVo@q!MP4@yHE&5RElw*HKWXcBs4q?FW?{6bO5+7> zOv>G_7FA2vq&{66FHB4u3I+mEfI=%&M)Ttn8-*(#kC&gcW?G7tSEa0>gY%N(frn6E zFLk#{n><AtP9>$}V86Rs>fVScu;m)<4yopJ(NZk6(%|A^;O-3{W9)Oa3w3NZQ2TBj zJ06gp4Y8jDYM%+QUj&*@hS(c{*b^c4c#ZT}h`m~qJRD*_3f=<b&%ws$>ewqQ1{nKR z?EsjTR}O%iKdjsZ_)499D~YJ!ytA*bTWZ}oII>adjJ8GNQd=zE8QU7~lv;<>F)5{3 z4&T(a5v|s8)4;(Y7MN)aG~ZkoIu3Icxp*~2QD-3BcwabFVS$6$jBQc(IMy}`yJ09q zkbuPC#Q}ee^@bb2T+<tFdL)<(OLHrF!>te3Cc?1?S0=(;N9(fTe>Df!)zpW(`ogh9 zxV1MdfiBqehC_+>p#3$Z5$aa3D~nz#K?aXZ4+%1O+j&UPiFR2{khzo07~ak`gxfg+ z)(pP@@q>Cof(+hZ9uj0Xc~AyX;=5<L1eteMf{d;hs&+xvP%V(FAj9k}m5<uR<?-Cf zd1$FR>)`yoF22<+*Rz*hd^_hZ%<##~AP=yJSRyIARL_ntp^WX~+^Mft4sjl$iRaZp z7OpCitDrra1i<AU_$|*4V<jIx>%&hV_n3y?_R;?#@HH^6VsJ*mdkEzP__fqj$5)KQ zYrwtYyy(MQATM6}TYUJi5C4J>KkdVR<-<de8?SgGK75-GzsH9^=)<4#;m`T-1s}d1 z9wlD!xBGC-htK-(AN%k{AATFm7q56yK779qf7FMc_TjJi@QXhDyFT+X43Ao`_~(7} znY=TzyEl=MWpjE|PRqNLf|gT1AI;~Pd{@rObjfl-FK7jeMKgUdJZ#28Cmy!oA&!SO zJapip9S>a<ue*2b$R&s6;Y4pHDTBwsoYhs(O?gx?)s8f{?TaV(dGUUm%VVZ4Pb%72 zQDw56pHXC37R*2}B?y!C?}-}fcvO}rW@h9m)i8BUDHf~)^1c`|515u(ay-X7pt(X` zE{vO&p(>?xK4-<_`ANl)Ekh|-W;<LLk`ztZ0|h5a8}9RV(RZ(Cl4<n>BU+&cqhJ z3=$DL)G(7nxx&z3P8Rjas!6;Z+`#fnH{`6Y7r}C9z(+HlQ>~GytYRo76ZJsNWlj86 z8;w&tq7je50(75h$S{`6nze)Ye=OULY0Vj)0jIZ}j@S07!k8D2$IMB6zYNPpOZBR6 zi%k^uQKcx4s-`8Ie2MI6It_G*b@P^SXVGj|=B$pqK5ao_VSGAeS$D=!E@-A|Sf0Z< zgd^z;JJ(LbG>pl~T&J8J$hFJG>M#{?40SszmG<pi=Jc)dF44+Z619eL7DGHL%*pF+ zxY}f;9cP|{$D*0`n3W#g$PYs&HbW=y4u$(k%x?XLW;Y+%c*iuP6bG<iT7|qx$A+XS z-Z27dxvJWAgu;8w?<zV`T{U!SyQ-GnS4%6!eJE%(L)X0j9rY1yKWw37+=7%;cw|;q zy72n4SEc`f?Iwy?Nx<XTUb6}=)^WHF#Pz@6>){#&{otno!CMf5xc&D!*ygzU6#9dl zW4mZ8xJCGFgxk9dD5E~*KOp)aBKkigJVN*%3I8zRmkIv};R}S{PWWnA$Dm+5t?(1^ zzn^g2SP72nEfmzpoC+Q%9Cn5k-cLAwTM+sg!Z#5<K{(adIL9_|ZzB9mbB^PM?^(gW zMEu}dU+}LI9wYn&@w1xn?+|_J=ck0niT-)Q+X(*+;rLZZ#Pd5J{yOK_uQf#fpF|(` zD#FhK;rN|T@YU!51jnlreuCdh_!h!(or;3`UGNk7cMy(yA;CKc?<RaZ;U6b_2jSZY zA0!;V1PlLre7M26dp;Z_`ZWJXIL8w{6NLXqi9Q|QuMtlDob=(RILFgk;{OcMr~c0o zPW``3IPNV)oEJEE_xJZipZfU==Xk<T>cY<zqEF-bH{sMz0M_LwI3FkvagJuRzfDA+ z`j-f&ep(5q{k@ZOcYnKyKJ}B}9OJnKexkphBKkC*&k|1kC_a3W_^17yA^Oz+VZy2Z zhkf{0i2wJI_@5&B)c>=DQ~%%h;V%&XH2z-_ed_<Wgj4^2Bb+`TE)!0l4_67N&xZg` zC=fi+=fh2e)91r#!s+v2y${EIBMP2A2|qC(wh~UC!wDab^A829KL9`B2N?=Jc43RR zOpx~wD)DQapH#n(aG`_fGlZi)zN=6a=VY%#mV7mfng>djGRmT`7I)5*;tIBCuw5Ke zEQLi!O_RYct*Atig0f;*(^DMbzEV~ULpcCIM+5X0kHVgk7Q0w<BA=JlnY=n>$<P?= z1|6Ta$+fnD(Y#*5uj?$T>6RLW&$^o+g#7*7UY(T3VaEmTCJY_Ix^cMxF7SQsmL3ko zcPD%&Nbuv+pmJ^ohGXgd9S<s8g1S^%pn#0u29+xJcRo?!w#T&^#^`77)_0e2ZGy}l ze-;?ZUeRHvxa?a6uE9{Hhu4eKLu;I?hj;=pe>hJ?KAX5=Kb-L^r91xTdAmZNt5@tr z8Sh=M_8W0vKtwy(K7NfB{shN<V*l|OM&%4|AMa@@B7fp6L#3DfYutXbP~=WT`vPm+ z9`Ac9tN4JRe=5RGuvxf37IZn7;`X9Fq3<pqh6=CzwR+?a_fW!K<nNonuzm6TflFIv zc>B0^ry}AP=jWkPTvNTL-4l{mx^-XT_O9-;Q{4U(bqd!aeu2-yg;)Q3c>niuMVvp4 z@Dui;|M={1&s{WmlH0$E1tRYFvFwf=)w4KRL7I3!@STi%Qg{3Kp9`<{Cs#oQ$OgRW Ih`8JTFU1~44gdfE literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Makefile new file mode 100644 index 0000000..71b1892 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/Makefile @@ -0,0 +1,24 @@ +include ../../environment + +all: MainLan MainSeq + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: newGA.req.o newGA.pro.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: newGA.req.o newGA.pro.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: newGA.req.o newGA.pro.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -np 10 ./MainLan Config.cfg + +WAN: + $(RUN) -v -p4pg pgfileWan MainWan + +SEQ: + ./MainSeq newGA.cfg ../../ProblemInstances/ONEMAX-instances/onemax10.txt res/sol.txt \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/asignacion_colores.csv b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/asignacion_colores.csv new file mode 100644 index 0000000..8384036 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/asignacion_colores.csv @@ -0,0 +1,10 @@ +1,5 +2,5 +3,5 +4,5 +5,5 +6,5 +7,5 +8,0 +9,4 +10,4 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_empleados b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_empleados new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_empleados @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_tareas b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_tareas new file mode 100644 index 0000000..301160a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_cantidad_tareas @@ -0,0 +1 @@ +8 \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_empleados b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_empleados new file mode 100644 index 0000000..f7cc5e5 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_empleados @@ -0,0 +1,4 @@ +e1 e2 e3 e4 e5 +4 5 5 3 3 +0.05 0.20 0.30 0.95 0.50 +120 200 210 230 180 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_tareas b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_tareas new file mode 100644 index 0000000..589272f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/datos_tareas @@ -0,0 +1,3 @@ +20 +t1 t2 t3 t4 t5 t6 t7 t8 +16 28 11 51 2 23 43 15 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/ejercicio2.py b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/ejercicio2.py new file mode 100644 index 0000000..6705a02 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/ejercicio2.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import random +import math +import os + +try: + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./ejercicio2 <ruta_tareas> <ruta_empleados> <ruta_solucion>" + sys.exit(1) + + ruta_tareas=sys.argv[1] + ruta_empleados=sys.argv[2] + ruta_solucion=sys.argv[3] + + os.system("make clean") + os.system("make all") + os.system("make SEQ") + + #os.system("python verificador.py " + ruta_tareas + " " + ruta_empleados + " " + ruta_solucion) + + """ + habilidad_empleados=[] + sueldo_diario_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + nombres_tareas=[] + nombre_empleados=[] + costo_proyecto=0 + tiempo_solucion_proyecto=0 + + # se sabe que son 3 lineas + archivo_tareas=open(ruta_tareas) + lineasTareas=archivo_tareas.readlines() + deadLine=lineasTareas[0] + nombres_tareas=lineasTareas[1].strip().split(" ") + esfuerzo_requerido_tarea=lineasTareas[2].strip().split(" ") + + # se sabe que son 4 lineas + archivo_empleados=open(ruta_empleados) + lineasEmpleados=archivo_empleados.readlines() + nombre_empleados=lineasEmpleados[0].strip().split(" ") + dedicacion_diaria_diponible_empleado=lineasEmpleados[1].strip().split(" ") + habilidad_empleados=lineasEmpleados[2].strip().split(" ") + sueldo_diario_empleado=lineasEmpleados[3].strip().split(" ") + + # se convierten a entero + dedicacion_diaria_diponible_empleado = map(int, dedicacion_diaria_diponible_empleado) + sueldo_diario_empleado = map(int, sueldo_diario_empleado) + deadLine=int(deadLine) + esfuerzo_requerido_tarea = map(int, esfuerzo_requerido_tarea) + + # se convierte a float + habilidad_empleados = map(float, habilidad_empleados) + + # se levanta la solucion del archivo + matriz_solucion=[] + + archivo_solucion=open(ruta_solucion) + + solucion_empleados_tareas=[] + solucion_empleados=[] + solucion_tareas=[] + + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + if( not (empleados_tareas[0] in nombre_empleados)): + print "No existe en la instancia el empleado: " + empleados_tareas[0] + sys.exit(1) + solucion_empleados.append(empleados_tareas[0]) + for i in range(1,len(empleados_tareas)): + if( not (empleados_tareas[i] in nombres_tareas)): + print "No existe en la instancia la terea: " + empleados_tareas[i] + sys.exit(1) + solucion_tareas.append(empleados_tareas[i]) + + + for i in range(0,len(solucion_empleados)): + for j in range(i+1,len(solucion_empleados)): + if(solucion_empleados[i]==solucion_empleados[j]): + print "Empleado repetido: " + solucion_empleados[i] + sys.exit(1) + + for i in range(0,len(solucion_tareas)): + for j in range(i+1,len(solucion_tareas)): + if(solucion_tareas[i]==solucion_tareas[j]): + print "Tarea asignada más de una vez: " + solucion_tareas[i] + sys.exit(1) + + + # todas las tareas asignadas + if(len(solucion_tareas)!=len(nombres_tareas)): + print "La cantidad de tareas asignadas es distinta a la cantidad de tareas de la instancia." + sys.exit(1) + + for i in range(0,len(nombres_tareas)): + if( not (nombres_tareas[i] in solucion_tareas)): + print "Tarea no asignada " + nombres_tareas[i] + sys.exit(1) + + costo_total=0 + archivo_solucion=open(ruta_solucion) + maximo_tiempo=0 + tiempo_en_dias=0 + # se hacen los calculos con la informacion en los archivos + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + indice_empleado = nombre_empleados.index(empleados_tareas[0]) + tiempo_en_horas=0 + for i in range(1,len(empleados_tareas)): + indice_tarea = nombres_tareas.index(empleados_tareas[i]) + tiempo_en_horas=tiempo_en_horas+(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias= int(math.ceil(tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado])) + costo_total=costo_total+sueldo_diario_empleado[indice_empleado]*tiempo_en_dias + if(tiempo_en_dias>maximo_tiempo): + maximo_tiempo=tiempo_en_dias + + if(maximo_tiempo<=deadLine): + # todo OK! + print costo_total,maximo_tiempo + else: + print "No cumple con el tiempo máximo de finalización ({0} > {1}).".format(maximo_tiempo, deadLine) + sys.exit(1) + + """ + +except IOError as error: + print error diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/generador.py b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/generador.py new file mode 100644 index 0000000..c699bd6 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/generador.py @@ -0,0 +1,143 @@ +import sys +import random +import math +from collections import defaultdict + +try: + #Constantes + mayor_duracion_horas_tarea=200 + menor_duracion_horas_tarea=12 + mayor_disponibilidad_diaria_horas_empleado=10 + menor_disponibilidad_diaria_horas_empleado=1 + sueldo_hora_base_empleado_sin_experiencia=110 + sueldo_valor_maximo_bono_por_buen_empleado_hora=23 + deadline_dias=0 + + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./generador <cant_tereas> <cant_empleados> <archivo_salida>" + sys.exit(1) + + cantidad_tareas=int(sys.argv[1]) + cantidad_empleados=int(sys.argv[2]) + archivo_salida=sys.argv[3] + + if (cantidad_tareas<1): + print "La cantidad de tareas debe ser mayor o igual a 1." + sys.exit(1) + + + if (cantidad_empleados<1): + print "La cantidad de empleados debe ser mayor o igual a 1." + sys.exit(1) + + if (cantidad_empleados>cantidad_tareas): + print "La cantidad de empleados debe ser menor a la cantidad de tareas." + sys.exit(1) + + + #VARIABLES: + + #habilidades de los empleados valor entre 0 y 1 + habilidad_empleados=[] + sueldo_semanal_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + + for i in range(0,cantidad_empleados): + dedicacion_diaria_diponible_empleado.append(random.randint(menor_disponibilidad_diaria_horas_empleado,mayor_disponibilidad_diaria_horas_empleado)) + + for i in range(0,cantidad_empleados): + habilidad_empleados.append(round(random.uniform(0, 1),2)) + + #los empleados cobran un bono (random) de rendimiento + #empleados con habilidad 0 cobran el sueldo de horas base por la cantidad de horas semanales + #empleados con habilidad mayor a 0 cobran un plus por habilidad proporcional a su habilidad + #empleado con habilidad 1 cobra aproximadamente el doble que el de experiencia 0 + for i in range(0,cantidad_empleados): + bono_por_buen_empleado=random.randint(0,sueldo_valor_maximo_bono_por_buen_empleado_hora) + sueldo_base=sueldo_hora_base_empleado_sin_experiencia+bono_por_buen_empleado + plus_por_experiencia=sueldo_hora_base_empleado_sin_experiencia*habilidad_empleados[i] + sueldo_semanal_empleado.append(int(math.ceil((sueldo_base+plus_por_experiencia)*dedicacion_diaria_diponible_empleado[i]))) + + for i in range(0,cantidad_tareas): + esfuerzo_requerido_tarea.append(random.randint(menor_duracion_horas_tarea,mayor_duracion_horas_tarea)) + + ###################### + #calculo del deadline + ###################### + + + tiempo_ocupado_empleado = {} + for indice_empleado in range(0,cantidad_empleados): + tiempo_ocupado_empleado[indice_empleado]=0 + + tiempo_en_horas=0 + tiempo_en_dias_con_decimales=0 + indice_empleado_menor_tiempo=0 + for indice_tarea in range(0,cantidad_tareas): + minimo_tiempo=sys.float_info.max + for indice_empleado in range(0,cantidad_empleados): + tiempo_en_horas=(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias_con_decimales= tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado] + tiempo_en_el_que_termina_si_se_le_da_esta_tarea=tiempo_ocupado_empleado[indice_empleado]+tiempo_en_dias_con_decimales + if(tiempo_en_el_que_termina_si_se_le_da_esta_tarea < minimo_tiempo): + indice_empleado_menor_tiempo=indice_empleado + minimo_tiempo=tiempo_en_el_que_termina_si_se_le_da_esta_tarea + tiempo_ocupado_empleado[indice_empleado_menor_tiempo]=minimo_tiempo + + + deadline_dias=0 + #busca maxima duracion + for indice_empleado in range(0,cantidad_empleados): + if(tiempo_ocupado_empleado[indice_empleado]>deadline_dias): + deadline_dias=tiempo_ocupado_empleado[indice_empleado] + + #print tiempo_ocupado_empleado + #se redondean los dias para pagar el dia entero a los que trabajan menos + deadline_dias=int(math.ceil(deadline_dias))*1.2 + + #archivo de salida de empleados + archivo = open ("%s_empleados"%archivo_salida, "w") + archivo.write("e%d"%1) + for i in range(1,cantidad_empleados): + #nombre del empleado + archivo.write(" e%d"%(i+1)) + archivo.write("\n") + archivo.write("%d"%dedicacion_diaria_diponible_empleado[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %d"%dedicacion_diaria_diponible_empleado[i]) + archivo.write("\n") + archivo.write("%.2f"%habilidad_empleados[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %.2f"%habilidad_empleados[i]) + archivo.write("\n") + archivo.write("%d"%sueldo_semanal_empleado[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %d"%sueldo_semanal_empleado[i]) + + #archivo de salida de tareas + archivo = open ("%s_tareas"%archivo_salida, "w") + archivo.write("%d"%deadline_dias) + archivo.write("\n") + archivo.write("t%d"%1) + for i in range(1,cantidad_tareas): + #nombre de la tarea + archivo.write(" t%d"%(i+1)) + archivo.write("\n") + archivo.write("%d"%esfuerzo_requerido_tarea[0]) + for i in range(1,cantidad_tareas): + archivo.write(" %d"%esfuerzo_requerido_tarea[i]) + + + #archivo cantidad de tareas + archivo = open ("%s_cantidad_tareas"%archivo_salida, "w") + archivo.write("%d"%cantidad_tareas) + + #archivo cantidad de trabajos + archivo = open ("%s_cantidad_empleados"%archivo_salida, "w") + archivo.write("%d"%cantidad_empleados) + + +except IOError as error: + print error diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.cfg new file mode 100644 index 0000000..c7caf7a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.cfg @@ -0,0 +1,18 @@ +10 // number of independent runs +100 // number of generations +60 // number of individuals +100 // size of offsprings in each generation +1 // if replaces parents for offsprings, or only offsprings may be new parents +1 // display state ? +Selections // selections to apply +1 3 // selection of parents +2 0 // selection of offsprings +Intra-Operators // operators to apply in the population +0 0.6 // crossover & its probability +1 1.0 0.01 // mutation & its probability +Inter-Operators // operators to apply between this population and anothers +0 10 5 1 3 1 5 // operator number, operator rate, number of individuals, selection of indidivual to send and remplace +LAN-configuration +1 // refresh global state +0 // 0: running in asynchronized mode / 1: running in synchronized mode +1 // interval of generations to check solutions from other populations diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.hh new file mode 100644 index 0000000..552b264 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.hh @@ -0,0 +1,868 @@ +/********************************************************************************************************* +*** *** +*** new Genetic Algorithm Skeleton v1.5 *** +*** Developed by: Gabriel Jesús Luque Polo *** +*** Last Update: 27-01-2003 *** +*** *** +*** tabular size = 4 *** +**********************************************************************************************************/ + +#ifndef INC_newGA +#define INC_newGA +#include "newGAstructures.hh" + +skeleton newGA +{ +// Si se definen más de 5 nuevos operadores por parte del usuario, se debe cambiar esta constante. +#define MAX_OP_USER 5 +// Si se algún operador tiene más de 5 parámetros se debe modificar esta variable +#define MAX_PROB_PER_OP 5 + + provides class SetUpParams; + provides class Statistics; + provides class Population; + provides class Inter_Operator; + provides class Migration; + provides class Selection; + provides class Selection_Tournament; + provides class Selection_Roulette_Wheel; + provides class Selection_Rank; + provides class Selection_Best; + provides class Selection_Worst; + provides class Operator_Pool; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + provides class StopCondition; + + requires class Problem; + requires class Solution; + requires class UserStatistics; + requires class Intra_Operator; + requires class Crossover; + requires class Mutation; + requires class StopCondition_1; + requires bool terminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem(); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int cantDias() const; + int cantEmpleados() const; + int dimension() const; + + Empleado * empleados() const; + int * tareasEsf() const; + int * tareasIndex() const; + int ** limite_barrios() const; + const char* getfield(char* line, int num); + + private: + int _cantDias; + Empleado * _empleados; + int * _tareasEsf; + int * _tareasIndex; + int _cantEmpleados; + int _dimension; + int ** _limite_barrios; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness (); + unsigned int size() const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + unsigned long nb_evaluation_best_found_trial; + unsigned long nb_iteration_best_found_trial; + double best_cost_trial; + double worst_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Intra_Operator ( clase abstracta ) -------------------------------------------------------------- + + requires class Intra_Operator + { + protected: + unsigned int _number_operator; + float *probability; + + public: + Intra_Operator(const unsigned int _number_op); + virtual ~Intra_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const Intra_Operator& intra); + + virtual void execute(Rarray<Solution*>& sols) const=0; + virtual void setup(char line[MAX_BUFFER]) = 0; + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const=0; + virtual void UpdateFromState(const StateCenter& _sc)=0; + }; + +// Crossover ---------------------------------------------------------------------------------- + + requires class Crossover: public Intra_Operator + { + public: + Crossover(); + virtual ~Crossover(); + + friend ostream& operator << (ostream& os, const Crossover& cross); + + void cross(Solution &sol1,Solution &sol2) const; + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Mutation ---------------------------------------------------------------------------------- + + requires class Mutation: public Intra_Operator + { + public: + Mutation(); + virtual ~Mutation(); + + friend ostream& operator<< (ostream& os, const Mutation& mutation); + + void mutate(Solution& sol) const; + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + + }; + +// StopCondition ---------------------------------------------------------------------------------- + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + +// StopCondition_1 {subclase------------------------------------------------------------------------- + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _nb_evolution_steps; + unsigned int _population_size; // number of individuals + unsigned int _population_additional_size; // size of offspring in each generation + bool _combine; // combines parents and offsprings to select new parents ? + bool _display_state; + + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _check_asynchronous; + + // selection of parents and offsprings + mutable unsigned int _select_parents; + mutable unsigned int _select_offsprings; + mutable unsigned int _parameter_select_parents; + mutable unsigned int _parameter_select_offsprings; + + Rlist<unsigned int> _intra_operators; + Rlist<unsigned int> _inter_operators; + + Operator_Pool& _pool; + + public: + SetUpParams (Operator_Pool& pool); + Operator_Pool& pool() const; + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long nb_evolution_steps() const; + const unsigned int population_size() const; + const unsigned int population_additional_size() const; + const bool combine() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int check_asynchronous() const; + + void independent_runs(const unsigned int val); + void nb_evolution_steps(const unsigned long val); + void population_size(const unsigned int val); + void population_additional_size(const unsigned int val); + void combine(const bool val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void check_asynchronous(const unsigned int val); + + // gets the i-th operator of inter-population + const unsigned int inter_operator_index(const unsigned int index) const; + const unsigned int inter_operators_size() const; + + // gets the i-th operator of intra-population + const unsigned int intra_operator_index(const unsigned int index) const; + const unsigned int intra_operators_size() const; + + const unsigned int select_parents() const; + const unsigned int select_offsprings() const; + const unsigned int parameter_select_parents() const; + const unsigned int parameter_select_offsprings() const; + + void select_parents(const unsigned int val); + void select_offsprings(const unsigned int val); + void parameter_select_parents(const unsigned int val); + void parameter_select_offsprings(const unsigned int val); + + void RefreshState(const StateCenter& _sc) const; + void UpdateFromState(const StateCenter& _sc) const; + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_generation; + unsigned long nb_evaluation; + double best_cost; + double global_best_cost; + double average_cost; + double standard_deviation; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + ~Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + }; + +// Population --------------------------------------------------------------------------------- + + provides class Population + { + private: + Rarray<Solution*> _parents; // individuals in population + Rarray<Solution*> _offsprings; // offsprings of current population + Rarray<Solution*> _new_parents; // individuals of previous population + Rarray<struct individual> _fitness_values; + Rarray<struct individual> _fitness_aux; + const SetUpParams& _setup; + unsigned int _upper_cost,_lower_cost; // lower and upper fitness of individuals in population + unsigned long _evaluations; + double _average_cost; + + inline void Evaluate(Solution* sols,struct individual &_f); + + public: + Population(const Problem& pbm,const SetUpParams& setup); // crea un array de objetos population; + ~Population(); + + friend ostream& operator<< (ostream& os, const Population& population); + friend istream& operator>> (istream& is, Population& population); + Population& operator= (const Population& pop); + const SetUpParams& setup() const; + void initialize(); + + // Generate a new pool of individuals in population + void evolution(); + + // interchange solutions between island + void interchange(const unsigned long current_generation, NetStream& channel); + + // creates a array with fitness of all individuals in population and its position in the population + void evaluate_parents(); + + // creates a array with fitness of all individuals and offsprings in population and its position in the population + void evaluate_offsprings(); + + // selects parents to creates offsprings + void select_parents(); + + // selects individuals for the new population + void select_offsprings(); + + const Rarray<Solution*>& parents() const; + const Rarray<Solution*>& offsprings() const; + Rarray<struct individual>& fitness_values(); + + unsigned int upper_cost() const; + unsigned int lower_cost() const; + unsigned int evaluations() const; + Solution& solution(const unsigned int index) const; + double fitness(const unsigned int index) const; + + double best_cost() const; + double worst_cost() const; + Solution& best_solution() const; + Solution& worst_solution() const; + double average_cost() const; + double standard_deviation() const; + }; + +// Inter_Operator ( abstract )----------------------------------------------------------- + + provides class Inter_Operator + { + protected: + unsigned int migration_rate; + unsigned int migration_size; + unsigned int migration_selection_1; + unsigned int migration_selection_2; + unsigned int migration_selection_conf_1; + unsigned int migration_selection_conf_2; + + unsigned int _number_operator; + const Direction direction; + + public: + Inter_Operator(const unsigned int _number_op, const Direction dir); + virtual ~Inter_Operator(); + + friend ostream& operator<< (ostream& os, const Inter_Operator& inter); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const=0; + virtual void setup(char line[MAX_BUFFER]); + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Migration: public Inter_Operator ----------------------------------------------------------- + + provides class Migration: public Inter_Operator + { + public: + Migration(const Direction dir); + virtual ~Migration(); + + friend ostream& operator<< (ostream& os, const Migration& migration); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const; + }; + +// Selection ( Makes a random selection ) ----------------------------------------- + + provides class Selection + { + protected: + unsigned int _number_selection; + const Direction direction; + + public: + + Selection(const Direction dir); + Selection(const unsigned int _number_sel, const Direction dir); + virtual ~Selection(); + + friend ostream& operator<< (ostream& os, const Selection& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + unsigned int number_selection() const; + }; + +// Selection_Tournament --------------------------------------------------------------------------------- + + provides class Selection_Tournament: public Selection + { + public: + Selection_Tournament(const Direction dir); + virtual ~Selection_Tournament(); + + friend ostream& operator<< (ostream& os, const Selection_Tournament& sel); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tourment_size,const bool remplace) const; + }; + +// Selection_Roulette_Wheel --------------------------------------------------------------------------------- + + provides class Selection_Roulette_Wheel: public Selection + { + public: + Selection_Roulette_Wheel(const Direction); + virtual ~Selection_Roulette_Wheel(); + + friend ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + }; + +// Selection_Rank --------------------------------------------------------------------------------- + + provides class Selection_Rank: public Selection + { + public: + Selection_Rank(const Direction dir); + Selection_Rank(const unsigned int _number_sel, const Direction dir); + virtual ~Selection_Rank(); + + friend ostream& operator<< (ostream& os, const Selection_Rank& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual void reset(); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const; + }; + +// Selection_Best --------------------------------------------------------------------------------- + + provides class Selection_Best: public Selection_Rank + { + private: + mutable unsigned int selection_best_position; + + public: + Selection_Best(const Direction); + virtual ~Selection_Best(); + + friend ostream& operator<< (ostream& os, const Selection_Best& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Selection_Worst --------------------------------------------------------------------------------- + + provides class Selection_Worst: public Selection_Rank + { + private: + mutable unsigned int selection_worst_position; + + public: + Selection_Worst(const Direction); + virtual ~Selection_Worst(); + + friend ostream& operator<< (ostream& os, const Selection_Worst& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Operator_Pool ------------------------------------------------------------------------- + + // pool with all operators and selections that can be chosen in the setup file + provides class Operator_Pool + { + private: + mutable Rlist<Intra_Operator> _intra_operators; + Rlist<Selection> _selectors; + Rlist<Inter_Operator> _inter_operators; + + public: + Operator_Pool(const Problem& pbm); + ~Operator_Pool(); + + Intra_Operator& intra_operator(const unsigned int index) const; + Rlist<Intra_Operator>& intra_operators() const; + Selection& selector(const unsigned int index) const; + const Rlist<Selection>& selectors() const; + Inter_Operator& inter_operator(const unsigned int index) const; + const Rlist<Inter_Operator>& inter_operators() const; + + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Population current_population; + StateCenter _sc; + + double best_cost; + double worst_cost; + Solution best_solution; + double average_cost; + double standard_deviation; + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_evaluations; + + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_worst_cost; + State_Vble _current_average_cost; + State_Vble _current_standard_deviation; + State_Vble _current_time_spent; + + State_Vble _best_solution_trial; + State_Vble _best_cost_trial; + State_Vble _worst_cost_trial; + State_Vble _iteration_best_found_in_trial; + State_Vble _evaluations_best_found_in_trial; + State_Vble _time_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _evaluations_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _global_worst_cost; + State_Vble _time_best_found; + + State_Vble _crossover_probability; // probability of applying the operator over population + State_Vble _mutation_probability; // probability of applying the operator over population + State_Vble _user_op_probability[MAX_OP_USER]; // probabilities of user operators + State_Vble _migration_rate; + State_Vble _migration_size; + State_Vble _migration_selection_1; + State_Vble _migration_selection_2; + State_Vble _migration_selection_conf_1; + State_Vble _migration_selection_conf_2; + State_Vble _select_parents; + State_Vble _select_offsprings; + State_Vble _parameter_select_parents; + State_Vble _parameter_select_offsprings; + + State_Vble _display_state; + + + public: + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + + virtual int pid() const; + bool end_trial() const; + void end_trial(bool et); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (const unsigned long int nb_generations) =0; + virtual void run (const Population& pop,const unsigned long int nb_generations) =0; + + //Partial execution + virtual void StartUp()=0; + virtual void StartUp(const Population& pop)=0; + + virtual void DoStep()=0; + + // Statistics handling ---------------------------------------------------------------------- + + Statistics& statistics(); + UserStatistics& userstatistics (); + Population& population(); + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling --------------------------------------------------------------------------- + + void RefreshState(); + void RefreshCfgState(); + void UpdateFromState(); + void UpdateFromCfgState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + unsigned long current_evaluations() const; + Solution current_best_solution() const; + double current_best_cost() const; + double current_worst_cost() const; + double current_average_cost() const; + double current_standard_deviation() const; + float current_time_spent() const; + Solution best_solution_trial() const; + double best_cost_trial() const; + double worst_cost_trial() const; + unsigned int iteration_best_found_in_trial() const; + unsigned int evaluations_best_found_in_trial() const; + float time_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + unsigned int evaluations_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + double global_worst_cost() const; + float time_best_found() const; + int display_state() const; + + float *crossover_probability() const; + float *mutation_probability() const; + float *user_op_probability(const int index) const; + unsigned int migration_rate() const; + unsigned int migration_size() const; + unsigned int migration_selection_1() const; + unsigned int migration_selection_2() const; + unsigned int migration_selection_conf_1() const; + unsigned int migration_selection_conf_2() const; + unsigned int select_parents() const; + unsigned int select_offprings() const; + unsigned int parameter_select_parents() const; + unsigned int parameter_select_offsprings() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_evaluations(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_worst_cost(const double value); + void current_average_cost(const double value); + void current_standard_deviation(const double value); + void current_time_spent(const float value); + void best_solution_trial(const Solution& sol); + void best_cost_trial(const double value); + void worst_cost_trial(const double value); + void iteration_best_found_in_trial(const unsigned int value); + void evaluations_best_found_in_trial(const unsigned int value); + void time_best_found_trial(const float value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void evaluations_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void global_worst_cost(const double value); + void time_best_found(const float value); + void display_state(const int value); + + void crossover_probability(const float *probability); + void mutation_probability(const float *probability); + void user_op_probability(const int index,const float *probability); + void migration_rate(const unsigned int rate); + void migration_size(const unsigned int size); + void migration_selection_1(const unsigned int seleciton_1); + void migration_selection_2(const unsigned int selection_2); + void migration_selection_conf_1(const unsigned int selection_conf_1); + void migration_selection_conf_2(const unsigned int selection_conf_2); + void select_parents(const unsigned int selection); + void select_offsprings(const unsigned int selection); + void parameter_select_parents(const unsigned int value); + void parameter_select_offsprings(const unsigned int value); + + void show_state() const; + void KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_trial,const float total_time_spent); + }; + + provides class Solver_Seq: public Solver + { + public: + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + int receive_local_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + unsigned long acum_iterations; + unsigned long acum_evaluations; + + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + //Communication + void send_local_state_to(int _mypid); + void check_for_refresh_global_state(); + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + int receive_local_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + unsigned long acum_iterations; + unsigned long acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + //Communication + void send_local_state_to(int _mypid); + void check_for_refresh_global_state(); + void reset(); + }; + +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.cc new file mode 100644 index 0000000..dfdd244 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.cc @@ -0,0 +1,2831 @@ +#include "newGA.hh" + +skeleton newGA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (Operator_Pool& pool) + : _independent_runs(0), + _nb_evolution_steps(0), + _population_size(0), + _population_additional_size(0), + _select_parents(0), + _select_offsprings(0), + _parameter_select_parents(0), + _parameter_select_offsprings(0), // Parameter of selection is fixed to 0 + _inter_operators(), + _intra_operators(), + _combine(1), + _refresh_global_state(1), + _synchronized(0), + _check_asynchronous(1), + _display_state(0), + _pool(pool) + {} + + Operator_Pool& SetUpParams::pool() const + { + return _pool; + } + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + long op; + int parameter; + short int nb_section=0; + short int nb_io = 0; + short int nb_selection = 0; + short int nb_param=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"Selections"))) nb_section=1; + if (!(strcmp(command,"Intra-Operators"))) nb_section=2; + if (!(strcmp(command,"Inter-Operators"))) nb_section=3; + if (!(strcmp(command,"LAN-configuration"))) nb_section=4; + + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.nb_evolution_steps(op); break; + case 2: setup.population_size(op); break; + case 3: setup.population_additional_size(op); break; + case 4: setup.combine(op); break; + case 5: setup.display_state(op); break; + } + nb_param++; + break; + case 1: op=-1; // creates the chosen selection method + parameter=0; + sscanf(buffer," %d %d",&op,¶meter); + if (nb_selection>=2) break; + assert(parameter>=0); + if (nb_selection==0) + { + setup.select_parents(op); + setup.parameter_select_parents(parameter); + } + else + { + setup.select_offsprings(op); + setup.parameter_select_offsprings(parameter); + } + nb_selection++; + break; + case 2: setup.pool().intra_operators().append(Intra_Operator::create(op)); + setup.pool().intra_operator(nb_io).setup(buffer); + setup._intra_operators.append(new unsigned int(nb_io)); + nb_io++; + break; + case 3: setup._inter_operators.append(new unsigned int(op)); + setup.pool().inter_operator(op).setup(buffer); + break; + case 4: if (nb_LAN_param>=3) break; + switch (nb_LAN_param) + { + case 0: setup.refresh_global_state(op); break; + case 1: setup.synchronized(op); break; + case 2: assert(op>0); + setup.check_asynchronous(op); break; + } + nb_LAN_param++; + break; + } + } + + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evolution steps: " << setup.nb_evolution_steps() << endl + << "\t" << "Size of Population: " << setup.population_size() << endl + << "\t" << "Size of Additional population: " << setup.population_additional_size() << endl; + if (setup.combine()) + os << "\t" <<"With combination between parents and offsprings" << endl; + else + os << "\t" <<"Without combination between parents and offsprings" << endl; + + os << "\t" << "Display State: " << setup.display_state() << endl << endl + << "\t" << "Selections:" << endl + << "\t" << "-----------" << endl << endl + << "\t" << "Selection parents -> " << setup.pool().selector(setup.select_parents()) << endl + << "\t" << "Parameter of selection: " << setup.parameter_select_parents() << endl + << "\t" << "Selection offsprings -> " << setup.pool().selector(setup.select_offsprings()) << endl + << "\t" << "Parameter of selection: " << setup.parameter_select_offsprings() << endl << endl + << "\t" << "Intra_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.intra_operators_size();i++) + os << "\t" << (setup.pool().intra_operator(setup.intra_operator_index(i))) << endl; + + os << endl << "\t" << "Inter_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.inter_operators_size();i++) + os << "\t" << "Operator: " << setup.pool().inter_operator(setup.inter_operator_index(i)) << endl; + + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + os << "\t" << "Interval for checking asynchronous receptions: " << setup.check_asynchronous() << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::nb_evolution_steps() const + { + return _nb_evolution_steps; + } + + const unsigned int SetUpParams::population_size() const + { + return _population_size; + } + + const unsigned int SetUpParams::population_additional_size() const + { + return _population_additional_size; + } + + const bool SetUpParams::combine() const + { + return _combine; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::check_asynchronous() const + { + return _check_asynchronous; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs=val; + } + + void SetUpParams::nb_evolution_steps(const unsigned long val) + { + _nb_evolution_steps=val; + } + + void SetUpParams::population_size(const unsigned int val) + { + _population_size=val; + } + + void SetUpParams::population_additional_size(const unsigned int val) + { + _population_additional_size=val; + } + + void SetUpParams::combine(const bool val) + { + _combine=val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::check_asynchronous(const unsigned int val) + { + _check_asynchronous=val; + } + + const unsigned int SetUpParams::select_parents() const + { + return _select_parents; + } + + const unsigned int SetUpParams::select_offsprings() const + { + return _select_offsprings; + } + + const unsigned int SetUpParams::parameter_select_parents() const + { + return _parameter_select_parents; + } + + const unsigned int SetUpParams::parameter_select_offsprings() const + { + return _parameter_select_offsprings; + } + + void SetUpParams::select_parents(const unsigned int val) + { + _select_parents=val; + } + + void SetUpParams::select_offsprings(const unsigned int val) + { + _select_offsprings=val; + } + + void SetUpParams::parameter_select_parents(const unsigned int val) + { + _parameter_select_parents=val; + } + + void SetUpParams::parameter_select_offsprings(const unsigned int val) + { + _parameter_select_offsprings=val; + } + + const unsigned int SetUpParams::intra_operator_index(const unsigned int index) const + { + return _intra_operators[index]; + } + + const unsigned int SetUpParams::intra_operators_size() const + { + return _intra_operators.size(); + } + + const unsigned int SetUpParams::inter_operator_index(const unsigned int index) const + { + return _inter_operators[index]; + } + + const unsigned int SetUpParams::inter_operators_size() const + { + return _inter_operators.size(); + } + + void SetUpParams::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_select_parents",(char *)&_select_parents,1,sizeof(_select_parents)); + _sc.set_contents_state_variable("_parameter_select_parents",(char *)&_parameter_select_parents,1,sizeof(_parameter_select_parents)); + _sc.set_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,1,sizeof(_select_offsprings)); + _sc.set_contents_state_variable("_parameter_select_offsprings",(char *)&_parameter_select_offsprings,1,sizeof(_parameter_select_offsprings)); + _sc.set_contents_state_variable("_display_state",(char *)&_display_state,1,sizeof(bool)); + } + + void SetUpParams::UpdateFromState(const StateCenter& _sc) const + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_select_parents",(char *)&_select_parents,nbytes,length); + _sc.get_contents_state_variable("_parameter_select_parents",(char *)&_parameter_select_parents,nbytes,length); + _sc.get_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_parameter_select_offsprings",(char *)&_parameter_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_display_state",(char *)&_display_state,nbytes,length); + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Trial: " << stats.stats_data[i].trial + << " Generation: " << stats.stats_data[i].nb_generation + << " Evaluation: " << stats.stats_data[i].nb_evaluation + << " Current best cost: " << stats.stats_data[i].best_cost + << " Global best cost: " << stats.stats_data[i].global_best_cost + << " Avg: " << stats.stats_data[i].average_cost + << " Std. Dev.: " << stats.stats_data[i].standard_deviation; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + struct stat *new_stat=(struct stat *)malloc(sizeof(struct stat)); + + new_stat->trial=solver.current_trial(); + new_stat->nb_generation=solver.current_iteration(); + new_stat->nb_evaluation=solver.current_evaluations(); + new_stat->average_cost=solver.current_average_cost(); + new_stat->standard_deviation=solver.current_standard_deviation(); + new_stat->best_cost=solver.current_best_cost(); + new_stat->global_best_cost=solver.global_best_cost(); + + stats_data.append(*new_stat); + } + + void Statistics::clear() + { + stats_data.remove(); + } + + Statistics::~Statistics() + {} + +// Population ------------------------------------------------------ + + Population::Population(const Problem& pbm,const SetUpParams& setup) + :_parents(setup.population_size()), + _fitness_values(setup.population_size()), + _new_parents(setup.population_size()), + _offsprings(setup.population_additional_size()), + _setup(setup), + _evaluations(0) + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]=new Solution(pbm); + _new_parents[i]=new Solution(pbm); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + for (int i=0;i<_offsprings.size();i++) + _offsprings[i]=new Solution(pbm); + + } + + void Population::Evaluate(Solution* sols,struct individual &_f) + { + if(_f.change) + { + _f.change = false; + _f.fitness = sols->fitness(); + _evaluations++; + } + } + + Population& Population::operator= (const Population& pop) + { + for (int i=0;i<_parents.size();i++) + { + *_parents[i]=*((pop.parents())[i]); + _fitness_values[i] = pop._fitness_values[i]; + _evaluations = pop._evaluations; + } + return (*this); + } + + istream& operator>> (istream& is, Population& population) + { + return is; + } + + ostream& operator<< (ostream& os, const Population& population) + { + os << "---------------------------------------------------------------" << endl; + os << " PRESENT POPULATION " << endl << endl; + for (int i=0;i<population._parents.size();i++) + os << *population._parents[i] << endl; + os << endl << "---------------------------------------------------------------" << endl; + return os; + } + + const SetUpParams& Population::setup() const + { + return _setup; + } + + void Population::initialize() + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]->initialize(); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + evaluate_parents(); + } + + void Population::evaluate_parents() + { + double upper_fitness=(infinity() * (-1)); + double lower_fitness=(infinity()); + double current_fitness; + double cost=0.0; + + for (int i=0;i<_fitness_values.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + current_fitness = _fitness_values[i].fitness; + + if (current_fitness > upper_fitness ) + { + _upper_cost=i; + upper_fitness = current_fitness; + } + + if (current_fitness < lower_fitness ) + { + _lower_cost=i; + lower_fitness = current_fitness; + } + + cost += current_fitness; + } + + _average_cost = cost / _fitness_values.size(); + } + + void Population::evaluate_offsprings() + { + int i=0; + if (_setup.combine()) // new individuals selected between current individuals and offsprings + { + _fitness_aux=Rarray<struct individual>(_parents.size() + _offsprings.size()); + for (i=0;i<_parents.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + _fitness_aux[i] = _fitness_values[i]; + } + + for (int j=i;(j-i)<_offsprings.size();j++) + { + _fitness_aux[j].index=j; + _fitness_aux[j].change=true; + Evaluate(_offsprings[j-i],_fitness_aux[j]); + } + } + else // new individuals selected only between offsprings + { + _fitness_aux=Rarray<struct individual>(_offsprings.size()); + for (i=0;i<_offsprings.size();i++) + { + _fitness_aux[i].index=i; + _fitness_aux[i].change=true; + Evaluate(_offsprings[i],_fitness_aux[i]); + } + } + } + + void Population::evolution() + { + select_parents(); // selects individuals to apply operators + + // apply selected operators + for (int i=0;i<_setup.intra_operators_size();i++) + _setup.pool().intra_operator(_setup.intra_operator_index(i)).execute(_offsprings); + + evaluate_offsprings(); + select_offsprings(); // selects new individuals + evaluate_parents(); // calculates fitness of new individuals + } + + void Population::interchange(const unsigned long current_generation, NetStream& channel) + { + // apply selected operators + for (int i=0;i<_setup.inter_operators_size();i++) + _setup.pool().inter_operator(_setup.inter_operator_index(i)).execute((*this),current_generation,channel,_setup.synchronized(),_setup.check_asynchronous()); + } + + void Population::select_parents() + { + _setup.pool().selector(_setup.select_parents()).prepare(_fitness_values,false); + struct individual ind; + for (int i=0;i<_offsprings.size();i++) + { + ind = _setup.pool().selector(_setup.select_parents()).select_one(_parents,_offsprings,_fitness_values,_setup.parameter_select_parents(),false); + *_offsprings[i] = *_parents[ind.index]; + } + } + + void Population::select_offsprings() + { + _setup.pool().selector(_setup.select_offsprings()).prepare(_fitness_aux,false); + const int ps = _parents.size(); + Rarray<struct individual> aux(ps); + + for (int i=0;i<ps;i++) + { + if (_setup.combine()) + { + aux[i] = _setup.pool().selector(_setup.select_offsprings()).select_one(_parents,_offsprings,_fitness_aux,_setup.parameter_select_offsprings(),false); + if(aux[i].index < ps) + { + *_new_parents[i] = *_parents[aux[i].index]; + aux[i].index = i; + } + else + { + *_new_parents[i] = *_offsprings[aux[i].index-ps]; + aux[i].index = i; + } + } + else + { + aux[i]=_setup.pool().selector(_setup.select_offsprings()).select_one(_offsprings,_offsprings,_fitness_aux,_setup.parameter_select_offsprings(),false); + *_parents[i] = *_offsprings[aux[i].index]; + aux[i].index = i; + } + } + + if (_setup.combine()) // interchanges current and new parents in the population + { + Solution *interchange; + for (int i=0;i<ps;i++) + { + interchange=_parents[i]; + _parents[i]=_new_parents[i]; // interchanges pointers to solutions ( NO solutions !! ) + _new_parents[i]=interchange; + } + } + for (int i=0;i<ps;i++) + { + _fitness_values[i] = aux[i]; + } + } + + const Rarray<Solution*>& Population::parents() const + { + return _parents; + } + + const Rarray<Solution*>& Population::offsprings() const + { + return _offsprings; + } + + Rarray<struct individual>& Population::fitness_values() + { + return _fitness_values; + } + + unsigned int Population::upper_cost() const + { + return _upper_cost; + } + + unsigned int Population::lower_cost() const + { + return _lower_cost; + } + + unsigned int Population::evaluations() const + { + return _evaluations; + } + + double Population::best_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_lower_cost].fitness; + else + return _fitness_values[_upper_cost].fitness; + } + + double Population::worst_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_upper_cost].fitness; + else + return _fitness_values[_lower_cost].fitness; + } + + Solution& Population::best_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_lower_cost].index]; + else + return *_parents[_fitness_values[_upper_cost].index]; + } + + Solution& Population::worst_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_upper_cost].index]; + else + return *_parents[_fitness_values[_lower_cost].index]; + } + + Solution& Population::solution(const unsigned int index) const + { + return *_parents[index]; + } + + double Population::fitness(const unsigned int index) const + { + return _fitness_values[index].fitness; + } + + double Population::average_cost() const + { + return _average_cost; + } + + double Population::standard_deviation() const + { + double standard=0.0; + for (int i=0;i<_fitness_values.size();i++) + standard += pow ((_fitness_values[i].fitness - _average_cost),2); + standard=sqrt(standard / (_fitness_values.size()-1)); + return standard; + } + + Population::~Population() + { + for (int i=0;i<_parents.size();i++) + delete(_parents[i]); + for (int i=0;i<_offsprings.size();i++) + delete(_offsprings[i]); + for (int j=0;j<_new_parents.size();j++) + delete(_new_parents[j]); + } + + +// Inter_operator ------------------------------------------------------------------- + + Inter_Operator::Inter_Operator(const unsigned int _number_op,const Direction dir): + _number_operator(_number_op), + direction(dir), + migration_rate(1), + migration_size(1), + migration_selection_1(0), + migration_selection_2(0), + migration_selection_conf_1(0), + migration_selection_conf_2(0) + {} + + unsigned int Inter_Operator::number_operator() const + { + return _number_operator; + } + + void Inter_Operator::setup(char line[MAX_BUFFER]) + { + int op; + int new_migration_rate=1; + int new_migration_size=1; + int new_migration_selection_1=0; + int new_migration_selection_conf_1=0; + int new_migration_selection_2=0; + int new_migration_selection_conf_2=0; + + sscanf(line," %d %d %d %d %d %d %d ",&op,&new_migration_rate,&new_migration_size,&new_migration_selection_1,&new_migration_selection_conf_1,&new_migration_selection_2,&new_migration_selection_conf_2); + + assert(new_migration_rate>0); + assert(new_migration_size>0); + assert(new_migration_selection_1>=0); + assert(new_migration_selection_conf_1>=0); + assert(new_migration_selection_2>=0); + assert(new_migration_selection_conf_2>=0); + + migration_rate=new_migration_rate; + migration_size=new_migration_size; + migration_selection_1=new_migration_selection_1; + migration_selection_conf_1=new_migration_selection_conf_1; + migration_selection_2=new_migration_selection_2; + migration_selection_conf_2=new_migration_selection_conf_2; + } + + void Inter_Operator::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_migration_rate",(char *)&migration_rate,1,sizeof(migration_rate)); + _sc.set_contents_state_variable("_migration_size",(char *)&migration_size,1,sizeof(migration_size)); + _sc.set_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,1,sizeof(migration_selection_1)); + _sc.set_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,1,sizeof(migration_selection_2)); + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,1,sizeof(migration_selection_conf_1)); + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,1,sizeof(migration_selection_conf_2)); + } + + void Inter_Operator::UpdateFromState(const StateCenter& _sc) + { + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&migration_rate,nitems,length); + _sc.get_contents_state_variable("_migration_size",(char *)&migration_size,nitems,length); + _sc.get_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,nitems,length); + } + + ostream& operator<< (ostream& os, const Inter_Operator& inter) + { + switch (inter.number_operator()) + { + case 0: os << (Migration&)inter;break; + } + return os; + } + + Inter_Operator::~Inter_Operator() + {} + +// Migration ------------------------------------------------------------ + + Migration::Migration(const Direction dir):Inter_Operator(0,dir) + {} + + void Migration::execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asynchronous) const + { + + Solution* solution_to_send; + Solution* solution_received; + Solution* solution_to_remplace; + bool need_to_revaluate=false; + int mypid; + + int nb_proc=_netstream.pnumber(); // Get the number of processes running + + mypid=_netstream.my_pid(); + + int to = (mypid + 1) % nb_proc; // Source (from) and Target (to) of processes + int from = (nb_proc + mypid - 1) % nb_proc; + + // process number 0 is only to store the global state + if (to==0) to=1; + if (from==0) from=nb_proc - 1; + + _netstream << set_target(to) << set_source(from) + << get_target(&to) << get_source(&from); + + if ( (current_generation % migration_rate) == 0 + && (current_generation!=pop.setup().nb_evolution_steps())) // in this generation this operator have to be applied + { + pop.setup().pool().selector(migration_selection_1).prepare(pop.fitness_values(),false); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to send + solution_to_send = pop.parents()[pop.setup().pool().selector(migration_selection_1).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_1,false).index]; + + _netstream << *solution_to_send; + } + _netstream << pack_end; + + if (synchronized) // synchronous mode: blocked until data are received + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << set_source(MPI_ANY_SOURCE); + int tipo = 0; + _netstream._wait2(any,tipo); + + if (tipo == 1){ + return; + } + + _netstream << wait(packed); + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } + _netstream << pack_end; + + } + } // end if + + if (!synchronized && ((current_generation % check_asynchronous) ==0)) + { // asynchronous mode: if there are not data, continue; + // but, if there are data, i have to receive it + int pending=false; + _netstream._probe(packed,pending); + if (pending) + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + pending=false; + _netstream._probe(regular,pending); + if (!pending) break; + + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } // end for + _netstream << pack_begin; + } // end if + } + + if (need_to_revaluate) pop.evaluate_parents(); + } + + ostream& operator<< (ostream& os, const Migration& migration) + { + os << "Migration." + << endl << "\t" << " Rate: " << migration.migration_rate + << endl << "\t" << " Size: " << migration.migration_size + << endl << "\t" << " Selection 1: " << migration.migration_selection_1 + << endl << "\t" << " Selection 1 Parameter: " << migration.migration_selection_conf_1 + << endl << "\t" << " Selection 2: " << migration.migration_selection_2 + << endl << "\t" << " Selection 2 Parameter: " << migration.migration_selection_conf_2; + return os; + } + + Migration::~Migration() + {} + +// Selection ------------------------------------------------------------ + + Selection::Selection(const Direction dir):_number_selection(0),direction(dir) + {} + + Selection::Selection(const unsigned int _number_sel, const Direction dir):_number_selection(_number_sel),direction(dir) + {} + + void Selection::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + {} + + struct individual Selection::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const + { // select a random individual + return fitness_values[rand_int(0,fitness_values.size()-1)]; + } + + unsigned int Selection::number_selection() const + { + return _number_selection; + } + + ostream& operator<< (ostream& os, const Selection& sel) + { + switch (sel.number_selection()) + { + case 0: os << "Random Selection"; break; + case 1: os << (Selection_Tournament&)sel; break; + case 2: os << (Selection_Roulette_Wheel&)sel; break; + case 3: os << (Selection_Rank&)sel; break; + case 4: os << (Selection_Best&)sel; break; + case 5: os << (Selection_Worst&)sel; break; + } + return os; + } + + Selection::~Selection() + {} + +// Selection_Tournament---------------------------------------------------- + + Selection_Tournament::Selection_Tournament(const Direction dir):Selection(1,dir) + {} + + struct individual Selection_Tournament::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tournament_size, const bool remplace) const + { + unsigned int best_sol=0; + double best_fitness=((-1) * direction * infinity()); + unsigned int index; + + if (remplace) best_fitness = -1 * best_fitness; + + unsigned int new_tournament_size=tournament_size; + if (tournament_size==0) new_tournament_size=1; + + for (int i=0;i<new_tournament_size;i++) + { + index=rand_int(0,fitness_values.size()-1); + + switch (direction) + { + case (minimize): if (((!remplace) && (fitness_values[index].fitness<best_fitness)) + || ((remplace) && (fitness_values[index].fitness>best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + case (maximize): if (((!remplace) && (fitness_values[index].fitness>best_fitness)) + || ((remplace) && (fitness_values[index].fitness<best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + } + } + + return fitness_values[best_sol]; + } + + ostream& operator<< (ostream& os, const Selection_Tournament& sel) + { + os << "Tournament Selection."; + return os; + } + + Selection_Tournament::~Selection_Tournament() + {} + +// Selection_Roulette_Wheel --------------------------------------------------- + + Selection_Roulette_Wheel::Selection_Roulette_Wheel(const Direction dir):Selection(2,dir) + {} + + void Selection_Roulette_Wheel::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + double overall_fitness=0.0; + + // inverts fitness values to select less fitness individuals with a high probability + if ((direction==maximize && (remplace)) || ((direction==minimize) && (!(remplace)))) + { + // fitness assigned if the fitness value is 0 in this case + double value_if_zero=DBL_MAX; + unsigned int nb_zeros=0; + + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + value_if_zero-=fitness_values[i].fitness; + else + nb_zeros++; + } + + value_if_zero=value_if_zero/nb_zeros; + + // Warning !! if fitness is 0 (1/0 ?) + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + fitness_values[i].sel_parameter = (1 / fitness_values[i].fitness ); + else + fitness_values[i].sel_parameter = value_if_zero; + overall_fitness+= fitness_values[i].sel_parameter; + } + } + else + { + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = fitness_values[i].fitness; + overall_fitness+= fitness_values[i].sel_parameter; + } + + } + + if (overall_fitness>DBL_MAX) overall_fitness=DBL_MAX; + + // calculate relative fitness + double previous=0.0; + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = (fitness_values[i].sel_parameter / overall_fitness) + previous; + previous = fitness_values[i].sel_parameter; + } + } + + struct individual Selection_Roulette_Wheel::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy, const bool remplace) const + { + double random_selected=rand01(); + int i=0; + + while (random_selected > fitness_values[i].sel_parameter ) + i++; + + return fitness_values[i]; + } + + ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel) + { + os << "Roulette Wheel Selection."; + return os; + } + + Selection_Roulette_Wheel::~Selection_Roulette_Wheel() + {} + +// Selection_Rank -------------------------------------------------- + + int lessF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness < i2.fitness; + } + + int greaterF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness > i2.fitness; + } + + Selection_Rank::Selection_Rank(const Direction dir):Selection(3,dir) + {} + + Selection_Rank::Selection_Rank(const unsigned int _number_sel, const Direction dir):Selection(_number_sel,dir) + {} + + void Selection_Rank::reset() + {} + + void Selection_Rank::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + reset(); + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(greaterF); + else + fitness_values.sort(lessF); + } + + struct individual Selection_Rank::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const + { + + unsigned int new_portion=portion; + if (portion==0 || portion>100) new_portion=100; + + return fitness_values[rand_int(0,(( fitness_values.size() * new_portion )/ 100)-1)]; + } + + ostream& operator<< (ostream& os, const Selection_Rank& sel) + { + os << "Rank-Ordered Selection."; + return os; + } + + Selection_Rank::~Selection_Rank() + {} + +// Selection_Best -------------------------------------------------- + + Selection_Best::Selection_Best(const Direction dir):Selection_Rank(4,dir),selection_best_position(0) + {} + + struct individual Selection_Best::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_best_position; + selection_best_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + return fitness_values[position_to_return]; + } + + void Selection_Best::reset() + { + selection_best_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Best& sel) + { + os << "Selection of best ordered individuals."; + return os; + } + + Selection_Best::~Selection_Best() + {} + +// Selection_Worst -------------------------------------------------- + + Selection_Worst::Selection_Worst(const Direction dir):Selection_Rank(5,dir),selection_worst_position(0) + {} + + struct individual Selection_Worst::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_worst_position; + selection_worst_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + int index=(fitness_values.size()-1) - position_to_return; + return fitness_values[index]; + } + + void Selection_Worst::reset() + { + selection_worst_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Worst& sel) + { + os << "Selection of worst ordered individuals."; + return os; + } + + Selection_Worst::~Selection_Worst() + {} + +// Operator_Pool ------------------------------------------------------------------------ + + Operator_Pool::Operator_Pool(const Problem& pbm) + { + // introduces all operators and selections in lists + + // Index to be chosen in setup file + //------------------------------------- + // The Intra_Operators are introduced dimanicly in setup + + _selectors.append(new Selection(pbm.direction())); // 0 + _selectors.append(new Selection_Tournament(pbm.direction())); // 1 + _selectors.append(new Selection_Roulette_Wheel(pbm.direction())); // 2 + _selectors.append(new Selection_Rank(pbm.direction())); // 3 + _selectors.append(new Selection_Best(pbm.direction())); // 4 + _selectors.append(new Selection_Worst(pbm.direction())); // 5 + + _inter_operators.append(new Migration(pbm.direction())); // 0 + } + + Intra_Operator& Operator_Pool::intra_operator(const unsigned int index) const + { + assert(index < _intra_operators.size()); + return _intra_operators[index]; + } + + Rlist<Intra_Operator>& Operator_Pool::intra_operators() const + { + return _intra_operators; + } + + Selection& Operator_Pool::selector(const unsigned int index) const + { + assert(index < _selectors.size()); + return _selectors[index]; + } + + const Rlist<Selection>& Operator_Pool::selectors() const + { + return _selectors; + } + + Inter_Operator& Operator_Pool::inter_operator(const unsigned int index) const + { + assert(index < _inter_operators.size()); + return _inter_operators[index]; + } + + const Rlist<Inter_Operator>& Operator_Pool::inter_operators() const + { + return _inter_operators; + } + + Operator_Pool::~Operator_Pool() + {} + +// Solver (superclasse)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + current_population(pbm,setup), + best_cost((-1) * pbm.direction() * infinity()), + worst_cost((-1) * best_cost), + best_solution(problem), + average_cost(0.0), + standard_deviation(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_evaluations("_current_evaluations",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_worst_cost("_current_worst_cost",_sc), + _current_average_cost("_current_average_cost",_sc), + _current_standard_deviation("_current_standard_deviation",_sc), + _current_time_spent("_current_time_spent",_sc), + _best_solution_trial("_best_sol_trial",_sc), + _best_cost_trial("_best_cost_trial",_sc), + _worst_cost_trial("_worst_cost_trial",_sc), + _iteration_best_found_in_trial("_iteration_best_found_in_trial",_sc), + _evaluations_best_found_in_trial("_evaluations_best_found_in_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found",_sc), + _evaluations_best_found("_evaluations_best_found",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _global_worst_cost("_global_worst_cost",_sc), + _time_best_found("_time_best_found",_sc), + _crossover_probability("_crossover_probability",_sc), + _mutation_probability("_mutation_probability",_sc), + _migration_rate("_migration_rate",_sc), + _migration_size("_migration_size",_sc), + _migration_selection_1("_migration_selection_1",_sc), + _migration_selection_2("_migration_selection_2",_sc), + _migration_selection_conf_1("_migration_selection_conf_1",_sc), + _migration_selection_conf_2("_migration_selection_conf_2",_sc), + _select_parents("_select_parents",_sc), + _select_offsprings("_select_offsprings",_sc), + _parameter_select_parents("_parameter_select_parents",_sc), + _parameter_select_offsprings("_parameter_select_offsprings",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_evaluations(0); + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + best_solution_trial(best_solution); + best_cost_trial(best_cost); + worst_cost_trial(worst_cost); + iteration_best_found_in_trial(0); + evaluations_best_found_in_trial(0); + time_best_found_trial(time_spent_in_trial); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + evaluations_best_found(0); + global_best_solution(best_solution); + global_best_cost(best_cost); + global_worst_cost(worst_cost); + time_best_found(total_time_spent); + + float prob[MAX_PROB_PER_OP] = {0.0}; + crossover_probability(prob); + mutation_probability(prob); + + char aux[] = "_user_op_probability"; + char nombre[30]; + for(int i = 0; i < MAX_OP_USER; i++) + { + sprintf(nombre,"%s%d",aux,i); + _user_op_probability[i].set_name((char *)nombre); + _sc.add(_user_op_probability[i]); + user_op_probability(i,prob); + } + + migration_rate(0); + migration_size(0); + migration_selection_1(0); + migration_selection_2(0); + migration_selection_conf_1(0); + migration_selection_conf_2(0); + select_parents(0); + select_offsprings(0); + parameter_select_parents(0); + parameter_select_offsprings(0); + display_state(setup.display_state()); + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + void Solver::end_trial(bool et) + { + _end_trial = et; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _current_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_iteration.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_evaluations() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_evaluations.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _current_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_average_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_average_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_standard_deviation() const + { + double value=0.0; + unsigned long nitems,length; + _current_standard_deviation.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::best_solution_trial() const + { + Solution sol(problem); + char data_stored[_best_solution_trial.get_nitems() + _best_solution_trial.get_length()]; + unsigned long nitems,length; + _best_solution_trial.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::best_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _best_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::worst_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _worst_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _global_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::global_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _display_state.get_contents((char *)&value, nitems, length); + return value; + } + + float *Solver::crossover_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::mutation_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_mutation_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::user_op_probability(const int index) const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.get_contents_state_variable(aux,(char *)¤t_probability,nitems,length); + return current_probability; + } + + unsigned int Solver::migration_rate() const + { + unsigned int rate=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&rate,nitems,length); + return rate; + } + + unsigned int Solver::migration_size() const + { + unsigned int size=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_size",(char *)&size,nitems,length); + return size; + } + + unsigned int Solver::migration_selection_1() const + { + unsigned int selection_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_1",(char *)&selection_1,nitems,length); + return selection_1; + } + + unsigned int Solver::migration_selection_2() const + { + unsigned int selection_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_2",(char *)&selection_2,nitems,length); + return selection_2; + } + + unsigned int Solver::migration_selection_conf_1() const + { + unsigned int selection_conf_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,nitems,length); + return selection_conf_1; + } + + unsigned int Solver::migration_selection_conf_2() const + { + unsigned int selection_conf_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,nitems,length); + return selection_conf_2; + } + + unsigned int Solver::select_parents() const + { + unsigned int select_parents=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_parents",(char *)&select_parents,nitems,length); + return select_parents; + } + + unsigned int Solver::select_offprings() const + { + unsigned int select_offsprings=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_offsprings",(char *)&select_offsprings,nitems,length); + return select_offsprings; + } + + unsigned int Solver::parameter_select_parents() const + { + unsigned int parameter_select_parents; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_parents",(char *)¶meter_select_parents,nitems,length); + return parameter_select_parents; + } + + unsigned int Solver::parameter_select_offsprings() const + { + unsigned int parameter_select_offsprings; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_offsprings",(char *)¶meter_select_offsprings,nitems,length); + return parameter_select_offsprings; + } + + void Solver::current_trial(const unsigned int value) + { + _current_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _current_iteration.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_evaluations(const unsigned long value) + { + _current_evaluations.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _current_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _current_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_worst_cost(const double value) + { + _current_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_average_cost(const double value) + { + _current_average_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_standard_deviation(const double value) + { + _current_standard_deviation.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::best_solution_trial(const Solution& sol) + { + _best_solution_trial.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::best_cost_trial(const double value) + { + _best_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::worst_cost_trial(const double value) + { + _worst_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::iteration_best_found_in_trial(const unsigned int value) + { + _iteration_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found_in_trial(const unsigned int value) + { + _evaluations_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found(const unsigned int value) + { + _evaluations_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _global_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _global_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::global_worst_cost(const double value) + { + _global_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::display_state(const int value) + { + _display_state.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::crossover_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_crossover_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::mutation_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_mutation_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::user_op_probability(const int index, const float *new_probability) + { + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.set_contents_state_variable(aux,(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::migration_rate(const unsigned int rate) + { + _sc.set_contents_state_variable("_migration_rate",(char *)&rate,1,sizeof(int)); + } + + void Solver::migration_size(const unsigned int size) + { + _sc.set_contents_state_variable("_migration_size",(char *)&size,1,sizeof(int)); + } + + void Solver::migration_selection_1(const unsigned int selection_1) + { + _sc.set_contents_state_variable("_migration_selection_1",(char *)&selection_1,1,sizeof(int)); + } + + void Solver::migration_selection_2(const unsigned int selection_2) + { + _sc.set_contents_state_variable("_migration_selection_2",(char *)&selection_2,1,sizeof(int)); + } + + void Solver::migration_selection_conf_1(const unsigned int selection_conf_1) + { + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,1,sizeof(int)); + } + + void Solver::migration_selection_conf_2(const unsigned int selection_conf_2) + { + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,1,sizeof(int)); + } + + void Solver::select_parents(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_parents",(char *)&selection,1,sizeof(int)); + } + + void Solver::select_offsprings(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_offsprings",(char *)&selection,1,sizeof(int)); + } + + void Solver::parameter_select_parents(const unsigned int value) + { + _sc.set_contents_state_variable("_parameter_select_parents",(char *)&value,1,sizeof(int)); + } + + void Solver::parameter_select_offsprings(const unsigned int value) + { + _sc.set_contents_state_variable("_parameter_select_offsprings",(char *)&value,1,sizeof(int)); + } + + Statistics& Solver::statistics() + { + return _stat; + } + + UserStatistics& Solver::userstatistics() + { + return _userstat; + } + + Population& Solver::population() + { + return current_population; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool worseG=false; + bool betterT=false; + bool worseT=false; + + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost > global_worst_cost()); + betterT = (best_cost < best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost > worst_cost_trial()); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost < global_worst_cost()); + betterT = (best_cost > best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost < worst_cost_trial()); + break; + } + + if (betterT) + { + best_solution_trial(best_sol); + best_cost_trial(best_cost); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_in_trial(current_iteration()); + evaluations_best_found_in_trial(current_evaluations()); + if (betterG) + { + global_best_solution(best_sol); + global_best_cost(best_cost); + time_best_found(time_spent_in_trial); + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + evaluations_best_found(current_evaluations()); + } + } + + if (worseT) + { + worst_cost_trial(worst_cost); + if (worseG) + global_worst_cost(worst_cost); + } + } + + StateCenter *Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::RefreshCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).RefreshState(_sc); + params.RefreshState(_sc); + } + + void Solver::UpdateFromState() + { + best_solution=current_best_solution(); + best_cost=current_best_cost(); + worst_cost=current_worst_cost(); + average_cost=current_average_cost(); + standard_deviation=current_standard_deviation(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).UpdateFromState(_sc); + params.UpdateFromState(_sc); + } + + void Solver::show_state() const + { + cout << endl << " Current State ---------------------------------------------" << endl; +/* cout << endl << "Selection parents -> " << select_parents(); + cout << endl << "Parameter of selection: " << parameter_select_parents(); + cout << endl << "Selection offsprings -> " << select_offprings(); + cout << endl << "Parameter of selection: " << parameter_select_offsprings() << endl; + cout << endl << "Crossover_probability: " << crossover_probability(); + cout << endl << "Mutation_probability: " << mutation_probability(); + cout << endl << "User_Operator_probability: " << user_op_probability(0); + cout << endl << "Migration_rate: " << migration_rate(); + cout << endl << "Migration_size: " << migration_size(); + cout << endl << "Migration_selection_1: " << migration_selection_1(); + cout << endl << "Migration_selection_conf_1: " << migration_selection_conf_1(); + cout << endl << "Migration_selection_2: " << migration_selection_2(); + cout << endl << "Migration_selection_conf_2: " << migration_selection_conf_2() << endl; +*/ cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current evaluations: " << current_evaluations(); + cout << endl << "Current best cost: " << current_best_cost(); + cout << endl << "Current worst cost: " << current_worst_cost(); + cout << endl << "Current Average cost: " << current_average_cost(); + cout << endl << "Current Standard Deviation: " << current_standard_deviation(); + cout << endl << endl << "Trial: "; + cout << endl << "Best cost trial: " << best_cost_trial(); + cout << endl << "Worst cost trial: " << worst_cost_trial(); + cout << endl << "Iteration best found in trial: " << iteration_best_found_in_trial(); + cout << endl << "Evaluations best found in trial: " << evaluations_best_found_in_trial(); + cout << endl << "Time best found trial: " << time_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << endl << "Global: "; + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Global worst cost: " << global_worst_cost(); + cout << endl << "Trial best found: " << trial_best_found(); + cout << endl << "Iteration best found: " << iteration_best_found(); + cout << endl << "Evaluations best found: " << evaluations_best_found(); + cout << endl << "Time best found: " << time_best_found(); +// cout << endl << endl << "Best Solution: " << endl << global_best_solution(); + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + } + +// Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Seq::StartUp(const Population& pop) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + time_best_found_trial(0.0); + + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + if( (current_iteration() % params.refresh_global_state()) == 0) + UpdateFromCfgState(); + + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Seq::run (const unsigned long int nb_generations) + { + StartUp(); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + void Solver_Seq::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + // Solver LAN ------------------------------------------------------------ + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Lan::StartUp(const Population& pop) + { + _netstream << barrier; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Lan::send_local_state_to(int _mypid) { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_solution_trial() + << current_best_solution() + << best_cost_trial() + << worst_cost_trial() + << time_best_found_trial() + << current_best_cost() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << pack_end; + } + + int Solver_Lan::receive_local_state() { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_solution_trial + >> best_solution + >> _best_cost_trial + >> _worst_cost_trial + >> _time_best_found_in_trial + >> best_cost + >> worst_cost + >> average_cost + >> standard_deviation + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + << pack_end; + return r_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_additional_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualizaci�n de las estad�sticas // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Lan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Wan::StartUp(const Population& pop) + { + _netstream << barrier; + + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_cost_trial() + << best_solution_trial() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << time_best_found_trial() + << worst_cost_trial() + << current_best_cost() + << current_best_solution() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << pack_end; + } + + int Solver_Wan::receive_local_state() + { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_cost_trial + >> _best_solution_trial + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + >> _time_best_found_in_trial + >> _worst_cost_trial + >> best_cost + >> best_solution + >> worst_cost + >> average_cost + >> standard_deviation + << pack_end; + return r_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_additional_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Update Stats // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Wan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i ; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + + } + _netstream << barrier; + } + +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.pro.o new file mode 100644 index 0000000000000000000000000000000000000000..8a79374826a57f9269ae72e0a8447080a445c8b4 GIT binary patch literal 176256 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�G)+fmTdpCWMjQv%L;MJqVt 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 Jnop6){{tn3<5mCw literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.cc new file mode 100644 index 0000000..653d43b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.cc @@ -0,0 +1,778 @@ +#ifndef INC_REQ_newGA +#define INC_REQ_newGA +#include "newGA.hh" +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sstream> +#include <algorithm> + +skeleton newGA +{ + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0),_limite_barrios(NULL),_tareasEsf(NULL),_tareasIndex(NULL),_empleados(NULL),_cantDias(0),_cantEmpleados(0) + { + //cout << "uf6"; + } + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + + //Imprimo el arreglo con los limites de barrios + os<<"Limites de barrios: "<<endl<<endl; + for (int i=0;i<pbm._dimension;i++){ + os<<i<<": "; + int indice=0; + while (pbm._limite_barrios[i][indice]!=-1){ + os<<pbm._limite_barrios[i][indice]<<","; + indice++; + } + os<<endl; + } + os<<endl; + return os; + } + + + + istream& operator>> (istream& is, Problem& pbm) + { + + char buffer[MAX_BUFFER]; + int i; + + //is.getline(buffer,MAX_BUFFER,'\n'); + //sscanf(buffer,"%d",&pbm._dimension); + + //CARGAR DATO CANT Tareas + ifstream inFile; + inFile.open("datos_cantidad_tareas"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + string x; + getline(inFile,x); + pbm._dimension = stoi(x); + inFile.close(); + + //Pido memoria para almacenar los limites de los barrios + pbm._limite_barrios=new int *[pbm._dimension]; + for (int i=0;i<pbm._dimension;i++) + { + pbm._limite_barrios[i]=new int [10]; + for (int j=0;j<10;j++) + pbm._limite_barrios[i][j]=-1; + } + + //CARGAR DATO CANT EMPLEADOS + inFile; + inFile.open("datos_cantidad_empleados"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + //string x; + getline(inFile,x); + pbm._cantEmpleados = stoi(x); + inFile.close(); + //INICIALIZAR DATOS TAREAS ESFUERZO + pbm._tareasEsf=new int [pbm._dimension]; + for (int ii=0;ii<pbm._dimension;ii++) + { + pbm._tareasEsf[ii]=0; + } + + + //CARGAR DATOS TAREAS ESFUERZO + + inFile.open("datos_tareas"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + string line2; + getline(inFile,line2); + pbm._cantDias = stoi(line2); + getline(inFile, line2); + getline(inFile, line2); + + int n = line2.length(); + char char_array[n+1]; + int len=1; + int t=0; + int z=0; + for(int i=0; i<=line2.length(); i++) + { + if(line2[i] == ' '|| i==line2.length()) + { + string rr = line2.substr(z,len); + pbm._tareasEsf[t] = stoi(rr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + inFile.close(); + + + pbm._tareasIndex = new int[pbm._dimension]; + for (int i = 0 ; i != pbm._dimension ; i++) + { + pbm._tareasIndex[i] = i; + } + sort(pbm._tareasIndex, pbm._tareasIndex + pbm._dimension,[&](const int& a, const int& b) { return (pbm._tareasEsf[a] < pbm._tareasEsf[b]); }); + /* + for (int i = 0 ; i != pbm._dimension ; i++) + { + cout << pbm._tareasIndex[i] << " "; + } + exit(0); + */ + + //INICIALIZAR EMPLEADOS + pbm._empleados=new Empleado [pbm._cantEmpleados]; + for (int zz=0;zz<pbm._cantEmpleados;zz++) + { + + pbm._empleados[zz]._sueldo = 0; + pbm._empleados[zz]._habilidad=0; + pbm._empleados[zz]._horas=0; + } + + //CARGAS DATOS EMPLEADOS + + string line23; + inFile.open("datos_empleados"); + getline(inFile, line23); + getline(inFile, line23); + int no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._horas = stoi(rrr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._horas <<" " << pbm._empleados[1]._horas <<" " << pbm._empleados[2]._horas <<" " << pbm._empleados[3]._horas << " " << pbm._empleados[4]._horas << " " << endl; + + getline(inFile, line23); + no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + // cout << line23; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._habilidad = stof(rrr); + //cout << rrr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._habilidad <<" " << pbm._empleados[1]._habilidad <<" " << pbm._empleados[2]._habilidad <<" " << pbm._empleados[3]._habilidad << " " << pbm._empleados[4]._habilidad << " " << endl; + + getline(inFile, line23); + no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._sueldo = stoi(rrr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._sueldo <<" " << pbm._empleados[1]._sueldo <<" " << pbm._empleados[2]._sueldo <<" " << pbm._empleados[3]._sueldo << " " << pbm._empleados[4]._sueldo << " " << endl; + //assert(false); + inFile.close(); + + /* + //Cargo el archivo con los limites de los barrios + FILE* stream = fopen("limite_barrios.csv", "r"); + + char line[1024]; + while (fgets(line, 1024, stream)) + { + char* tmp = strdup(line); + const char * barrio = pbm.getfield(tmp,1); + int barrio_int=atoi(barrio); + tmp = strdup(line); + const char * limite= pbm.getfield(tmp,2); + int i=0; + while (limite!=NULL) + { + pbm._limite_barrios[barrio_int-1][i]=atoi(limite)-1; + i++; + tmp = strdup(line); + limite=pbm.getfield(tmp,i+2); + } + free(tmp); + } + */ + cout<<pbm; + return is; + } + + //Funcion para leer el archivo CSV + const char* Problem::getfield(char* line, int num) + { + const char* tok; + for (tok = strtok(line, ","); + tok && *tok; + tok = strtok(NULL, ",\n")) + { + if (!--num) + return tok; + } + return NULL; + } + + int ** Problem::limite_barrios() const{ + return _limite_barrios; + } + + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + int Problem::cantEmpleados() const + { + return _cantEmpleados; + } + int Problem::cantDias() const + { + return _cantDias; + } + + int * Problem::tareasEsf() const + { + return _tareasEsf; + } + + int * Problem::tareasIndex() const + { + return _tareasIndex; + } + + Empleado *Problem::empleados() const + { + return _empleados; + } + + Problem::~Problem() + { + //Libero la memoria pedida para almacenar los limites de los barrios + for (int i=0;i<_dimension;i++) + delete [] _limite_barrios[i]; + delete [] _limite_barrios; + delete [] _empleados; + delete [] _tareasEsf; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + + //for (int i=0;i<sol.pbm().dimension();i++) + // os << " " << sol._var[i]; + stringstream ss; + + ofstream outfile("solution"); + + os << endl; + + for (int j = 0; j < sol.pbm().cantEmpleados(); j++) + { + bool found1 = false; + for (int i = 0; i < sol.pbm().dimension(); i++) + { + if (sol._var[i] == j) + { + if (!found1) + { + ss << "e" << j + 1; + found1 = true; + } + + ss << " t" << sol.pbm().tareasIndex()[i] + 1; + } + } + + if (found1) + { + ss << endl; + } + } + + outfile << ss.str(); + outfile.close(); + + os << ss.str(); + + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + for(int i = 0; i < _var.size(); i++) + if(_var[i] != sol._var[i]) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + //cout << _pbm.dimension(); + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=rand_int(0,_pbm.cantEmpleados() - 1); + //_var[i]=rand_int(0,3); + } + } + + double Solution::fitness () + { + + double fitness = 0.0; + double* horasTrabajados = new double[_pbm.cantEmpleados()]; + for (int q=0; q < _pbm.cantEmpleados(); q++) + { + horasTrabajados[q] = 0; + } + + for (int i=0;i< _pbm.dimension();i++) + { + Empleado tipo = _pbm.empleados()[_var[i]]; + double horasReq = ((double)_pbm.tareasEsf()[_pbm.tareasIndex()[i]]/(double)(0.5+tipo._habilidad)); + horasTrabajados[_var[i]] += horasReq; + + } + + + for (int j = 0; j < _pbm.cantEmpleados(); j++) + { + double diasTrabajadosTemp = (double)horasTrabajados[j] / (double)_pbm.empleados()[j]._horas; + fitness += (double)diasTrabajadosTemp * (double)_pbm.empleados()[j]._sueldo; + if (isnan(fitness)) + exit(0); + if (diasTrabajadosTemp > _pbm.cantDias()) + { + fitness += 100000; + } + } + + return fitness; + + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].worst_cost_trial + << "\t\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t\t" << userstat.result_trials[i].nb_iteration_best_found_trial + << "\t\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + void UserStatistics::update(const Solver& solver) + { + if( (solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().nb_evolution_steps()) + && !terminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial = solver.evaluations_best_found_in_trial(); + new_stat->nb_iteration_best_found_trial = solver.iteration_best_found_in_trial(); + new_stat->worst_cost_trial = solver.worst_cost_trial(); + new_stat->best_cost_trial = solver.best_cost_trial(); + new_stat->time_best_found_trial = solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// Intra_operator -------------------------------------------------------------- + + Intra_Operator::Intra_Operator(const unsigned int _number_op):_number_operator(_number_op),probability(NULL) + {} + + unsigned int Intra_Operator::number_operator() const + { + return _number_operator; + } + + Intra_Operator *Intra_Operator::create(const unsigned int _number_op) + { + switch (_number_op) + { + case 0: return new Crossover;break; + case 1: return new Mutation();break; + } + } + + ostream& operator<< (ostream& os, const Intra_Operator& intra) + { + switch (intra.number_operator()) + { + case 0: os << (Crossover&)intra;break; + case 1: os << (Mutation&)intra;break; + } + return os; + } + + Intra_Operator::~Intra_Operator() + {} + +// Crossover:Intra_operator ------------------------------------------------------------- + + Crossover::Crossover():Intra_Operator(0) + { + probability = new float[1]; + } + + void Crossover::cross(Solution& sol1,Solution& sol2) const // dadas dos soluciones de la poblacion, las cruza + { + //Usamos cruzamiento de dos puntos (2PX) + int i=0; + Rarray<int> aux(sol1.pbm().dimension()); + aux=sol2.array_var(); + + /* + if (current_time_spent() < 1000000) + { + int limit=rand_int((0,sol1.pbm().dimension()-1)); + + for (i=0;i<limit;i++) + sol2.var(i)=sol1.var(i); + for (i=0;i<limit;i++) + sol1.var(i)=aux[i]; + } + if (current_time_spent() >= 1000000) + {*/ + int limit=rand_int((sol1.pbm().dimension()/2)+1,sol1.pbm().dimension()-1); + int limit2=rand_int(0,limit-1); + + for (i=0;i<limit2;i++) + sol2.var(i)=sol1.var(i); + for (i=0;i<limit2;i++) + sol1.var(i)=aux[i]; + for (i=limit;i<sol1.pbm().dimension();i++) + sol2.var(i)=sol1.var(i); + for (i=limit;i<sol1.pbm().dimension();i++) + sol1.var(i)=aux[i]; + //} + } + + void Crossover::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i+1<sols.size();i=i+2) + if (rand01()<=probability[0]) cross(*sols[i],*sols[i+1]); + } + + ostream& operator<< (ostream& os, const Crossover& cross) + { + os << "Crossover." << " Probability: " + << cross.probability[0] + << endl; + return os; + } + + void Crossover::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_crossover_probability",(char *)probability,1,sizeof(float)); + } + + void Crossover::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)probability,nbytes,length); + } + + void Crossover::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f ",&op,&probability[0]); + assert(probability[0]>=0); + } + + Crossover::~Crossover() + { + delete [] probability; + } + + // Mutation: Sub_operator ------------------------------------------------------------- + + Mutation::Mutation():Intra_Operator(1) + { + probability = new float[2]; + } + + void Mutation::mutate(Solution& sol) const + { + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability[1]) + { + //La mutacion modifica un gen aleatoriamente con probabilidad uniforme en {0,3} + int temp = rand_int(0,sol.pbm().cantEmpleados() - 1); + sol.var(i)= temp; + //sol.var(i)=rand_int(0,3); + } + } + } + + void Mutation::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i<sols.size();i++) + if(rand01() <= probability[0]) mutate(*sols[i]); + } + + ostream& operator<< (ostream& os, const Mutation& mutation) + { + os << "Mutation." << " Probability: " << mutation.probability[0] + << " Probability1: " << mutation.probability[1] + << endl; + return os; + } + + void Mutation::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f %f ",&op,&probability[0],&probability[1]); + assert(probability[0]>=0); + assert(probability[1]>=0); + } + + void Mutation::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_mutation_probability",(char *)probability,2,sizeof(probability)); + } + + void Mutation::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_mutation_probability",(char *)probability,nbytes,length); + } + + Mutation::~Mutation() + { + delete [] probability; + } + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + bool fin=(int) (solver.current_time_spent() - solver.time_best_found_trial()) > 20000000; + //Condicion de parada. Si el fitness es 0 terminamos la ejecucion. + //bool fin=(int)solver.best_cost_trial() == 0; + //cout << pbm.cantEmpleados(); + /*if (fin){ + //Escribo el resultado en el archivo de salida + FILE * pFile; + pFile = fopen ("asignacion_colores.csv","w"); + for (int i=0;i<pbm.dimension();i++){ + fprintf (pFile, "%d,%d\n",i+1,solver.best_solution_trial().var(i)); + } + fclose (pFile); + }*/ + //return (fin); + return fin; + + } + + StopCondition_1::~StopCondition_1() + {} + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool terminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} +#endif + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.o b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGA.req.o new file mode 100644 index 0000000000000000000000000000000000000000..b38ae8dbb12876fd40eff199783aea8c7db92186 GIT binary patch literal 65312 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 z≷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 AX#fBK literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGAstructures.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGAstructures.hh new file mode 100644 index 0000000..d542639 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/newGAstructures.hh @@ -0,0 +1,60 @@ +#ifndef INC_newGA_mallba_hh +#define INC_newGA_mallba_hh + + +#include <iostream> +#include <fstream> +#include <math.h> +#include <limits.h> +#include <float.h> +#include <Rlist.h> +#include <Rarray.h> +#include <Messages.h> +#include <mallba.hh> +#include <States.hh> +#include <random.hh> +#include <time.hh> +#include <netstream.hh> +#include <assert.h> + +using namespace std; + +#ifndef _INDIVIDUAL_ +#define _INDIVIDUAL_ + +struct individual // index of a individual in the population and its fitness +{ + int index; + double fitness; + double sel_parameter; + bool change; +}; +struct Empleado // index of a individual in the population and its fitness +{ + int _horas; + float _habilidad; + double _sueldo; +}; + + +/*int lessF(const struct individual &i1,const struct individual &i2) +{ + return i1.fitness < i2.fitness; +} + +int lessS(const struct individual &i1,const struct individual &i2) +{ + return i1.sel_parameter < i2.sel_parameter; +} + +int greaterF(const struct individual &i1,const struct individual &i2) +{ + return i1.fitness > i2.fitness; +} + +int greaterS(const struct individual &i1,const struct individual &i2) +{ + return i1.sel_parameter > i2.sel_parameter; +}*/ +#endif +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_empleados b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_empleados new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_empleados @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_tareas b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_tareas new file mode 100644 index 0000000..301160a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_cantidad_tareas @@ -0,0 +1 @@ +8 \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_empleados b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_empleados new file mode 100644 index 0000000..f7cc5e5 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_empleados @@ -0,0 +1,4 @@ +e1 e2 e3 e4 e5 +4 5 5 3 3 +0.05 0.20 0.30 0.95 0.50 +120 200 210 230 180 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_tareas b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_tareas new file mode 100644 index 0000000..589272f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/datos_tareas @@ -0,0 +1,3 @@ +20 +t1 t2 t3 t4 t5 t6 t7 t8 +16 28 11 51 2 23 43 15 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/empty.txt b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/sol.txt b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/sol.txt new file mode 100644 index 0000000..94d8af3 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/res/sol.txt @@ -0,0 +1,16 @@ + +--------------------------------------------------------------- + STATISTICS OF TRIALS +------------------------------------------------------------------ + +1 10029.7 210883 1060 10 1591 14184 +2 10010.4 210882 5560 55 6233 12361 +3 10010.4 210656 4160 41 8672 14731 +4 10009.9 210921 160 1 106 9399 +5 10010.4 210807 4660 46 4349 9349 +6 10010.4 210921 760 7 657 9224 +7 10016.5 210990 3060 30 5449 11825 +8 10015.4 210452 4960 49 5341 10215 +9 10035.1 210876 5960 59 5591 9491 +10 10017.7 210873 360 3 295 9422 +------------------------------------------------------------------ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/solution b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/solution new file mode 100644 index 0000000..534d0b7 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/solution @@ -0,0 +1,3 @@ +e1 t3 t1 +e3 t5 t6 t4 +e4 t8 t2 t7 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/verificador.py b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/verificador.py new file mode 100644 index 0000000..0924a32 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/GA/verificador.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import random +import math + +try: + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./validador <ruta_tareas> <ruta_empleados> <ruta_solucion>" + sys.exit(1) + + ruta_tareas=sys.argv[1] + ruta_empleados=sys.argv[2] + ruta_solucion=sys.argv[3] + habilidad_empleados=[] + sueldo_diario_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + nombres_tareas=[] + nombre_empleados=[] + costo_proyecto=0 + tiempo_solucion_proyecto=0 + + # se sabe que son 3 lineas + archivo_tareas=open(ruta_tareas) + lineasTareas=archivo_tareas.readlines() + deadLine=lineasTareas[0] + nombres_tareas=lineasTareas[1].strip().split(" ") + esfuerzo_requerido_tarea=lineasTareas[2].strip().split(" ") + + # se sabe que son 4 lineas + archivo_empleados=open(ruta_empleados) + lineasEmpleados=archivo_empleados.readlines() + nombre_empleados=lineasEmpleados[0].strip().split(" ") + dedicacion_diaria_diponible_empleado=lineasEmpleados[1].strip().split(" ") + habilidad_empleados=lineasEmpleados[2].strip().split(" ") + sueldo_diario_empleado=lineasEmpleados[3].strip().split(" ") + + # se convierten a entero + dedicacion_diaria_diponible_empleado = map(int, dedicacion_diaria_diponible_empleado) + sueldo_diario_empleado = map(int, sueldo_diario_empleado) + deadLine=int(deadLine) + esfuerzo_requerido_tarea = map(int, esfuerzo_requerido_tarea) + + # se convierte a float + habilidad_empleados = map(float, habilidad_empleados) + + # se levanta la solucion del archivo + matriz_solucion=[] + + archivo_solucion=open(ruta_solucion) + + solucion_empleados_tareas=[] + solucion_empleados=[] + solucion_tareas=[] + + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + if( not (empleados_tareas[0] in nombre_empleados)): + print "No existe en la instancia el empleado: " + empleados_tareas[0] + sys.exit(1) + solucion_empleados.append(empleados_tareas[0]) + for i in range(1,len(empleados_tareas)): + if( not (empleados_tareas[i] in nombres_tareas)): + print "No existe en la instancia la terea: " + empleados_tareas[i] + sys.exit(1) + solucion_tareas.append(empleados_tareas[i]) + + + for i in range(0,len(solucion_empleados)): + for j in range(i+1,len(solucion_empleados)): + if(solucion_empleados[i]==solucion_empleados[j]): + print "Empleado repetido: " + solucion_empleados[i] + sys.exit(1) + + for i in range(0,len(solucion_tareas)): + for j in range(i+1,len(solucion_tareas)): + if(solucion_tareas[i]==solucion_tareas[j]): + print "Tarea asignada más de una vez: " + solucion_tareas[i] + sys.exit(1) + + + # todas las tareas asignadas + if(len(solucion_tareas)!=len(nombres_tareas)): + print "La cantidad de tareas asignadas es distinta a la cantidad de tareas de la instancia." + sys.exit(1) + + for i in range(0,len(nombres_tareas)): + if( not (nombres_tareas[i] in solucion_tareas)): + print "Tarea no asignada " + nombres_tareas[i] + sys.exit(1) + + costo_total=0 + archivo_solucion=open(ruta_solucion) + maximo_tiempo=0 + tiempo_en_dias=0 + # se hacen los calculos con la informacion en los archivos + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + indice_empleado = nombre_empleados.index(empleados_tareas[0]) + tiempo_en_horas=0 + for i in range(1,len(empleados_tareas)): + indice_tarea = nombres_tareas.index(empleados_tareas[i]) + tiempo_en_horas=tiempo_en_horas+(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias= int(math.ceil(tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado])) + costo_total=costo_total+sueldo_diario_empleado[indice_empleado]*tiempo_en_dias + if(tiempo_en_dias>maximo_tiempo): + maximo_tiempo=tiempo_en_dias + + if(maximo_tiempo<=deadLine): + # todo OK! + print costo_total,maximo_tiempo + else: + print "No cumple con el tiempo máximo de finalización ({0} > {1}).".format(maximo_tiempo, deadLine) + sys.exit(1) + +except IOError as error: + print error diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/Makefile new file mode 100644 index 0000000..2b7ed15 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/Makefile @@ -0,0 +1,6 @@ +all: + (cd CHC ; make) + (cd GA ; make) +clean: + (cd CHC ; make clean) + (cd GA ; make clean) \ No newline at end of file diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Config.cfg new file mode 100644 index 0000000..c515435 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +Instance Problem Path +Result File Path diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainWan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainWan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/MainWan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Makefile new file mode 100644 index 0000000..43b74fa --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan MainWan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/instance.txt res/res.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.cfg new file mode 100644 index 0000000..290f7e9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.cfg @@ -0,0 +1,9 @@ + // number of independent runs + // number of evaluations + // Markov-Chain Length (temperature is updated in every number of evaluations) + // temperature Decay + // display state ? +LAN-configuration + // the global state is updated in this number of evaluations + // 0: asynchronized mode // 1: synchronized mode + // interval of iterations to cooperate (if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.hh new file mode 100644 index 0000000..9c7901a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.hh @@ -0,0 +1,478 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + private: + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.req.cc new file mode 100644 index 0000000..6532801 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/SA.req.cc @@ -0,0 +1,222 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + +// Problem --------------------------------------------------------------- + Problem::Problem () + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + Problem::~Problem() + {} + +// Solution -------------------------------------------------------------- + Solution::Solution (const Problem& pbm):_pbm(pbm) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + {} + + double Solution::fitness () const + { + return 0.0; + } + + char *Solution::to_String() const + { + return NULL; + } + + void Solution::to_Solution(char *_routes_) + {} + + unsigned int Solution::size() const + { + return 0; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + // Body of operator + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.cc new file mode 100644 index 0000000..79e3342 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((solver.current_trial()==setup.independent_runs()) && (solver.current_iteration()==setup.max_evaluations())); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.cpp new file mode 100644 index 0000000..64d179a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.cpp @@ -0,0 +1,286 @@ +/*********************************************************************** + * File: AdjKeys.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file AdjKeys.h. + ***********************************************************************/ + +#include "AdjKeys.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +AdjKeys::AdjKeys(int * parent1, int * parent2, int nbOfFrag):nof(nbOfFrag) +{ + offSpring = new int[nof]; + share = new bool[nof]; + remaining = new int[nof]; + + aKeys = new int *[nof]; + for(int i = 0; i < nof; i++) + { + aKeys[i] = new int[4]; // [0] and [1] for parent1; [2] and [3] for parent2 + for(int j = 0; j < 4; j++) + aKeys[i][j] = -1; // initialize to -1 + } + + for(int k = 0; k < nof; k++) + { + offSpring[k] = -1; + share[k] = false; + remaining[k] = 0; + } + startKey = parent1[0]; // start key point to the first fragment of parent1 + makeAdjKeysTable(parent1, parent2); +} + +/************************* + * Purpose: release memory + *************************/ + +AdjKeys::~AdjKeys() +{ + for(int i = 0; i < nof; i++) + delete [] aKeys[i]; + + delete [] aKeys; + delete [] remaining; + delete [] share; + delete [] offSpring; +} + +/**************************************************** + * Purpose: create an adjacency table for two parents + ****************************************************/ + +void AdjKeys::makeAdjKeysTable(int * parent1, int * parent2) +{ + initAdjacentcy(parent1, 1); + initAdjacentcy(parent2, 2); + + setSharing(); +// printInfo(); +} + +/******************************************* + * Purpose: initialize a parent's adjacency + *******************************************/ + +void AdjKeys::initAdjacentcy(int * parent, int pid) +{ + int indStart; + if(pid == 1) + indStart = 0; // because aKeys[][0] and aKeys[][1] for parent1 + else + indStart = 2; // because aKeys[][2] and aKeys[][3] for parent2 + + int m = 0; + for(int i = 0; i < nof; i++) + { + int key = parent[m]; + + if(m == 0) // deal with the first fragment + { + aKeys[key][indStart] = parent[m+1]; + incrementRemaining(key); + } + else if(m == nof-1) // deal with the last fragment + { + aKeys[key][indStart] = parent[m-1]; + incrementRemaining(key); + } + else // deal with the middle fragments + { + aKeys[key][indStart] = parent[m-1]; + incrementRemaining(key); + aKeys[key][indStart+1] = parent[m+1]; + incrementRemaining(key); + } + m++; + } +} + +/*********************************************** + * Purpose: return number of remaining fragments + ***********************************************/ + +int AdjKeys::getRemaining(int id) +{ + return remaining[id]; +} + +/************************************************** + * Purpose: decrement number of remaining fragments + **************************************************/ + +void AdjKeys::decrementRemaining(int id) +{ + remaining[id]--; +} + +/************************************************** + * Purpose: increment number of remaining fragments + **************************************************/ + +void AdjKeys::incrementRemaining(int id) +{ + remaining[id]++; +} + +/**************************************************** + * Purpose: set the share to be true if the fragments + * are ajdacent to both parents. + ****************************************************/ + +void AdjKeys::setSharing() +{ + for(int i = 0; i < nof; i++) + { + if(aKeys[i][0] == aKeys[i][2] || aKeys[i][0] == aKeys[i][3]) + { + share[i] = true; + remaining[i]--; + } + if(aKeys[i][1] != -1) + { + if(aKeys[i][1] == aKeys[i][2] || aKeys[i][1] == aKeys[i][3]) + { + share[i] = true; + remaining[i]--; + } + } + } +} + +/************************************ + * Purpose: check the sharing status + ************************************/ + +bool AdjKeys::hasSharing(int id) +{ + return share[id]; +} + +/***************************************************** + * Purpose: print the detail information in this class + *****************************************************/ + +void AdjKeys::printInfo() +{ + for(int i = 0; i < nof; i++) + { + cout << aKeys[i][0] << ", " << aKeys[i][1] << ", " + << aKeys[i][2] << ", " << aKeys[i][3] << "\t"; + + cout << "sharing = " << share[i] << ", " << " remain = " << remaining[i] << endl; + } +} + +/***************************************************************** + * Purpose: reset the adjacent key to be -1 if it is already taken + *****************************************************************/ + +void AdjKeys::deleteTakenKey(int takenKey) +{ + int p, q; + for(p = 0; p < nof; p++) + { + if(takenKey != p) + { + bool exist = false; + for(q = 0; q < 4; q++) + { + if(aKeys[p][q] != -1 && aKeys[p][q] == takenKey) + { + aKeys[p][q] = -1; + exist = true; + } + } + if(exist) + decrementRemaining(p); + } + } +} + +/*********************************************************** + * Purpose: performs the actual edge-recombination operation + ***********************************************************/ + +void AdjKeys::recombine() +{ + int currKey = startKey; + offSpring[0] = currKey; + deleteTakenKey(currKey); + + int i; + // produce offspring based on adjacent keys + + for(i = 1; i < nof; i++) + { + int flag = false; + int tempKeys[4] = {-1, -1, -1, -1}; + int w = 0; + for(int j = 0; j < 4; j++) + { + int t = aKeys[currKey][j]; + if(t != -1 && hasSharing(t)) + { + currKey = t; + flag = true; + break; + } + else + { + if(t != -1) + tempKeys[w++] = t; + continue; + } + } + if(!flag) + { + if(w != 0) + { + int tk = tempKeys[0]; + int moreAdjLeft = getRemaining(tk); + currKey = tk; + for(int v = 1; v < w; v++) + { + tk = tempKeys[v]; + int adjLeft = getRemaining(tk); + if(adjLeft > moreAdjLeft) + { + moreAdjLeft = adjLeft; + currKey = tk; + } + } + } + else + break; + } + offSpring[i] = currKey; + deleteTakenKey(currKey); + } + + if(i < nof) // handle special case + { + for(int x = 0; x < nof; x++) + { + if(getRemaining(x) != 0) + { + for(int y = 0; y < 4; y++) + { + if(aKeys[x][y] != -1) + { + offSpring[i++] = aKeys[x][y]; + deleteTakenKey(aKeys[x][y]); + } + } + } + } + } +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.h new file mode 100644 index 0000000..cf440b2 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AdjKeys.h @@ -0,0 +1,45 @@ +/********************************************************************* + * File: AdjKeys.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: AdjKeys class is a helper class for Edge-recombination + * crossover operator + *********************************************************************/ + +#ifndef ADJKEYS_H +#define ADJKEYS_H + +#include <iostream> +#include <string> + +using namespace std; + +class AdjKeys +{ +public: + int startKey; + int * offSpring; // store offspring generate by crossover operator + + AdjKeys(int * parent1, int * parent2, int nbOfFrag); + ~AdjKeys(); + void makeAdjKeysTable(int * parent1, int * parent2); + void initAdjacentcy(int * parent, int pid); + void recombine(); + void deleteTakenKey(int takenKey); + int getRemaining(int id); + void setSharing(); + bool hasSharing(int id); + void decrementRemaining(int id); + void incrementRemaining(int id); + void printInfo(); +private: + int ** aKeys; // store adjacent keys for both parents + bool * share; // store sharing info for both parents + int * remaining; // store remaining fragments + int nof; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AlignedPair.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AlignedPair.h new file mode 100644 index 0000000..a5d0872 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/AlignedPair.h @@ -0,0 +1,39 @@ +/********************************************************************* + * File: AlignedPair.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: AlignedPair class is a helper class that wraps an + * alignment of two sequences + *********************************************************************/ + +#ifndef ALIGNEDPAIR_H +#define ALIGNEDPAIR_H + +#include <iostream> +#include <string> + +using namespace std; + +class AlignedPair +{ +public: + string s; // to store sequence s after alignment + string t; // to store sequence t after alignment + + AlignedPair() {} + AlignedPair(const string &s, const string &t) + { + this->s = s; + this->t = t; + } + + void printAlign() + { + cout << s << "\n" << t << endl << endl; + } +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Config.cfg new file mode 100644 index 0000000..8175e18 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/DNAFA-instances/pbm.txt +res/dna.sa.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.cpp new file mode 100644 index 0000000..ad8879e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.cpp @@ -0,0 +1,286 @@ +/*********************************************************************** + * File: ConsensusBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file ConsensusBuilder.h. + ***********************************************************************/ + +#include "ConsensusBuilder.h" + +int Global_cutoff; + +/***************************************************** + * Purpose: build the initial consensuses from contigs + *****************************************************/ + +ConsensusBuilder::ConsensusBuilder(vector<string> &SACons) +{ + consensus = SACons; + scpList = new List1<SubConsensusPair>(); +} + +/************************* + * Purpose: release memory + *************************/ + +ConsensusBuilder::~ConsensusBuilder() +{ + delete scpList; +} + +/********************************************** + * Purpose: postprocess four types of consensus + **********************************************/ + +void ConsensusBuilder::buildConsensus() +{ + if(consensus.size() > 1) + { +// cout << endl << "case FF" << endl; +/**/ cerr << "case FF" << endl; + buildSubConsensus(FF); // both from forward strand +/**/ cerr << "End case FF" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case FR" << endl; +/**/ cerr << "case FR" << endl; + buildSubConsensus(FR); // first from forward, second from reverse complement +/**/ cerr << "End case FR" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case RF" << endl; +/**/ cerr << "case RF" << endl; + buildSubConsensus(RF); // first from reverse complement, second from forward +/**/ cerr << "End case RF" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case RR" << endl;; +/**/ cerr << "case RR" << endl; + buildSubConsensus(RR); // both from reverse complement +/**/ cerr << "End case RR" << endl; + } + } + } + } +} + +/********************************************** + * Purpose: initialize four types of consensus + **********************************************/ + +void ConsensusBuilder::initST(int type) +{ + vector<string> rc; + for(int k = 0; k < consensus.size(); k++) + rc.push_back(Util::rcSequence(consensus[k])); + + s.clear(); + t.clear(); + switch(type) + { + case FF: + s = t = consensus; + break; + case FR: + s = consensus; + t = rc; + break; + case RF: + s = rc; + t = consensus; + break; + case RR: + s = t = rc; + break; + } +} + +/******************************************************** + * Purpose: detects the overlap for all possible pair of + * consensus and stores the overlap score in a + * sorted linked list in descending order. + ********************************************************/ + +void ConsensusBuilder::buildSubConsensus(int type) +{ +// cout << "\nCurrent consensus (" << type << ")" << endl; + //print(); + initST(type); + + for(int i = 0; i < s.size(); i++) + { + for(int j = i+1; j < s.size(); j++) // compute half of pairs only + { + SGA *sga = new SGA(s[i], t[j]); // eg. w1 and w2 +/**/ cerr << "Building Matrix " << i << " " << j << endl; + sga->buildMatrix(); + sga->findBestScore(); + int score = sga->getBestScore(); + delete sga; +/**/ cerr << "End Building Matrix " << i << " " << j << endl; + + if(score >= Global_cutoff) + { + scpList->insert(SubConsensusPair(i, j, score)); + scpList->insert(SubConsensusPair(j, i, score)); + } + } + } +// scpList->printList(); +/**/ cerr << "Updating Consensus" << endl; + updateConsensus(type); +/**/ cerr << "End Updating Consensus" << endl; +} + +/************************************************************ + * Purpose: update consensus information by aligning possible + * overlapping consensuses. + ************************************************************/ + +void ConsensusBuilder::updateConsensus(int type) +{ + vector<string> tempLayout; + vector<string> tepCon = consensus; + consensus.clear(); + + ListNode<SubConsensusPair>* tempNode = scpList->header->next; + + while(tempNode != NULL) + { + int cid1 = tempNode->data.cid1; + int cid2 = tempNode->data.cid2; + char direction = 'F'; // forward + + tempLayout.push_back(s[cid1]); + tempLayout.push_back(t[cid2]); + if(type == FR) + direction = 'R'; // reverse complement + + tepCon.at(cid1) = ""; + tepCon.at(cid2) = ""; + remove(scpList, cid1); + bool found = true; + while(found) + { + ListNode<SubConsensusPair>* nextNode = search(scpList, cid2); + if(nextNode == NULL) + found = false; + else + { + cid1 = cid2; + cid2 = nextNode->data.cid2; + + if(type == FR && direction == 'R') + { + tempLayout.push_back(s[cid2]); // s[cid2] = Util::rcSequence(t[cid2]) + direction = 'F'; + } + else if (type == FR && direction == 'F') + { + tempLayout.push_back(t[cid2]); + direction = 'R'; + } + else if (type == RF && direction == 'F') + { + tempLayout.push_back(s[cid2]); + direction = 'R'; + } + else + { + tempLayout.push_back(t[cid2]); + direction = 'F'; + } + + tepCon.at(cid2) = ""; + remove(scpList, cid1); + } + } + + if(tempLayout.size() > 1) + { + LayoutBuilder layoutBuilder(tempLayout); + layoutBuilder.findAlignments(); + // layoutBuilder.printAlignments(); + layoutBuilder.buildLayout(); +// cout << endl << "Merging =>"<< endl << endl; + layoutBuilder.printLayout(); + layoutBuilder.findConsensus(); + layoutBuilder.printConsensus(); + consensus.push_back(layoutBuilder.getConsensus()); + } + else + consensus.push_back(tempLayout.at(0)); + + tempLayout.clear(); + tempNode = scpList->header->next; + } + + for(int m = 0; m < tepCon.size(); m++) + { + if(tepCon.at(m) != "") + consensus.push_back(tepCon.at(m)); + } +} + +/************************************************************ + * Purpose: removes SubConsensusPair objects that contain the + * given id from the linked list. + ************************************************************/ + +void ConsensusBuilder::remove(List1<SubConsensusPair>* list, int cid) +{ + List1<SubConsensusPair>* temp = list; + ListNode<SubConsensusPair>* tempCurr = temp->header->next; + ListNode<SubConsensusPair>* tempPrev = temp->header; + + while(tempCurr != NULL) + { + if(tempCurr->data.cid1 == cid || tempCurr->data.cid2 == cid ) + { + ListNode<SubConsensusPair>* oldNode = tempCurr; + tempPrev->next = tempCurr->next; + tempCurr = tempCurr->next; + delete oldNode; + (temp->len)--; + } + else + { + tempPrev = tempCurr; + if(tempCurr != NULL) + tempCurr = tempCurr->next; + } + } +} + +/************************************************************ + * Purpose: find the SubConsensusPair object that contain the + * given id in the linked list. + ************************************************************/ + +ListNode<SubConsensusPair>* ConsensusBuilder::search(List1<SubConsensusPair>* list, int cid) +{ + ListNode<SubConsensusPair>* curr; + + for(curr = list->header->next; curr != NULL; curr = curr->next) + { + if(curr->data.cid1 == cid) // found + return curr; + } + return NULL; +} + +/*********************************** + * Purpose: prints current consensus + ***********************************/ + +void ConsensusBuilder::print() +{ +/* for(int j = 0; j < consensus.size(); j++) + cout << endl << "Cons #" << j << " => " << consensus.at(j); + cout << endl; +*/} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.h new file mode 100644 index 0000000..ea813d3 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ConsensusBuilder.h @@ -0,0 +1,53 @@ +/********************************************************************* + * File: ConsensusBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This ConsensusBuilder class is used to determine the + * sequence for contigs. + *********************************************************************/ + +#ifndef CONSENSUSBUILDER_H +#define CONSENSUSBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> +#include "list.h" +#include "Util.h" +#include "ContigBuilder.h" +#include "LayoutBuilder.h" +#include "scp.h" + +using namespace std; + +class ConsensusBuilder +{ +public: + // F - forward; R - reverse complement + enum TableType { FF, FR, RF, RR }; + + ConsensusBuilder(vector<string> &SACons); + ~ConsensusBuilder(); + + void initLayout(); // initialize layout + void buildConsensus(); + void updateConsensus(int type); + void remove(List1<SubConsensusPair> * list, int cid); + ListNode<SubConsensusPair> * search(List1<SubConsensusPair> * list, int cid); + vector<string> getConsensus() { return consensus; } + void print(); +private: + void buildSubConsensus(int type); + void initST(int type); + + List1<SubConsensusPair>* scpList; // a list of SubConsensusPair objects + vector<string> consensus; + vector<string> s, t; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.cpp new file mode 100644 index 0000000..dd7dc6f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.cpp @@ -0,0 +1,238 @@ +/*********************************************************************** + * File: ContigBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file ContigBuilder.h. + ***********************************************************************/ + +#include "ContigBuilder.h" + +/****************************************************** + * Purpose: initialize fragment order and overlap score + ******************************************************/ + +ContigBuilder::ContigBuilder(int * order, int ** s, const SA::Problem *pbm):_pbm(pbm) +{ + fragOrder = order; + score = s; +} + +/******************************************************* + * Purpose: construct contigs based on the overlap score + * of adjacent fragments + *******************************************************/ + +void ContigBuilder::buildContigs() +{ + vector<int> tempOrder; + + int id1 = fragOrder[0]; + tempOrder.push_back(id1+1); // +1 because 0 has no negative number + int direction = 1; + + for(int i = 1; i < _pbm->numOfFragments; i++) + { + int id2 = fragOrder[i]; + // cout << "score[" << id1 << "][" << id2 << "] = " << score[id1][id2] << endl; + + int sign = direction * score[id1][id2]; + + if(abs(score[id1][id2]) >= _pbm->cutoff) // default cutoff = 30bps + { + if(sign > 0) // from same strand + { + tempOrder.push_back(id2+1); + direction = 1; + } + else // from different strand + { + tempOrder.push_back(-(id2+1)); + direction = -1; + } + id1 = id2; + } + else + { + allContigs.push_back(tempOrder); // a new contig is formed + tempOrder.clear(); + id1 = id2; + tempOrder.push_back(id1+1); + direction = 1; + } + } + allContigs.push_back(tempOrder); +} + +/******************************************************* + * Purpose: merge two contigs and update the orientation + * accordingly + *******************************************************/ + +void ContigBuilder::mergeTwoContig(int cid1, int cid2) +{ + vector<int> fids1 = allContigs.at(cid1); + vector<int> fids2 = allContigs.at(cid2); + + int fid1 = fids1.at(fids1.size()-1); + int fid2 = fids2.at(0); + int sign = fid1 * fid2; + + bool type = score[abs(fid1)-1][abs(fid2)-1] > 0; + + bool flag = (!type && sign < 0) || (type && sign > 0); // flag = true => not change + + for(int i = 0; i < fids2.size(); i++) + { + if(flag) // don't change + allContigs.at(cid1).push_back(fids2.at(i)); + else // change + allContigs.at(cid1).push_back(-fids2.at(i)); + } + + allContigs.erase(allContigs.begin() + cid2); +} + +/***************************************************** + * Purpose: merge contigs that satisfy the predefined + * threshold + *****************************************************/ + +void ContigBuilder::mergeContigs() +{ + while(allContigs.size() >= 2) + { + int bestScore = _pbm->cutoff; + int cid_i = -1; + int cid_j = -1; + + for(int i = 0; i < allContigs.size()-1; i++) + { + vector<int> tempi = allContigs.at(i); + int fidi_First = abs(tempi.at(0)) - 1; + int fidi_Last = abs(tempi.at(tempi.size()-1)) - 1; + + for(int j = i+1; j < allContigs.size(); j++) + { + vector<int> tempj = allContigs.at(j); + + int fidj_First = abs(tempj.at(0)) - 1; + int fidj_Last = abs(tempj.at(tempj.size()-1)) - 1; + + if(abs(score[fidi_Last][fidj_First]) >= bestScore) // put contig_j after contig_i + { + bestScore = abs(score[fidi_Last][fidj_First]); + cid_i = i; + cid_j = j; + } + if(abs(score[fidj_Last][fidi_First]) > bestScore) // put contig_j before contig_i + { + bestScore = abs(score[fidj_Last][fidi_First]); + cid_i = j; + cid_j = i; + } + } + } + + if(cid_i != -1 && cid_j != -1) + mergeTwoContig(cid_i, cid_j); + else + break; + } + cerr << endl << "*** *** *** *** SA Contigs ( " << allContigs.size() << " ) *** *** *** ***" << endl << endl; +} + +/******************************************* + * Purpose: build consensus for each contigs + *******************************************/ + +void ContigBuilder::buildConsensus() +{ + vector< vector<string> > fragLayouts; + for(int i = 0; i < allContigs.size(); i++) + fragLayouts.push_back(getPreLayoutFrags(allContigs.at(i))); + + vector<string> SACons; + cerr << endl << "*** *** *** *** SA Contigs ( " << fragLayouts.size() << " ) *** *** *** ***" << endl << endl; + + for(int j = 0; j < fragLayouts.size(); j++) + { + vector<string> layout = fragLayouts.at(j); + +// cout << endl << "Fragments Layout (" << j << ") =>" << endl << endl; + + if(layout.size() > 1) + { + LayoutBuilder layoutBuilder(layout); + layoutBuilder.findAlignments(); + // layoutBuilder.printAlignments(); + layoutBuilder.buildLayout(); + layoutBuilder.printLayout(); + layoutBuilder.findConsensus(); + layoutBuilder.printConsensus(); + SACons.push_back(layoutBuilder.getConsensus()); + } + else + { + SACons.push_back(layout.at(0)); +// cout << layout.at(0) << endl; + } + } + ConsensusBuilder * cb = new ConsensusBuilder(SACons); +/**/ cerr << "Building Consensus" << endl; + cb->buildConsensus(); +/**/ cerr << "End Building Consensus" << endl; + + vector<string> finalCons = cb->getConsensus(); + cerr << endl << "*** *** *** *** Final Contigs ( " << finalCons.size() << " ) *** *** *** ***" << endl << endl; +/* for(int k = 0; k < finalCons.size(); k++) + { + cout << ">Contig #" << k << endl; + cout << finalCons.at(k) << endl; + } + cout << endl << "*****************************************************" << endl; +*/ delete cb; +} + +/******************************************************** + * Purpose: returns a vector of fragments associated with + * the fragment order + ********************************************************/ + +vector<string> ContigBuilder::getPreLayoutFrags(vector<int> order) +{ + vector<string> preLayoutFrags; + + for(int i = 0; i < order.size(); i++) + { + int fid = order.at(i); + if( fid > 0) // -1 because +1 when insert + preLayoutFrags.push_back(_pbm->fragments->at(fid-1)); + else + preLayoutFrags.push_back(_pbm->rcFragments->at(abs(fid)-1)); + } +// cout << endl; + return preLayoutFrags; +} + +/*********************************************** + * Purpose: print fragment order for each contig + ***********************************************/ + +void ContigBuilder::printOrder() +{ +/* cout << endl << "Contig size = " << allContigs.size() << endl; + + for(int i = 0; i < allContigs.size(); i++) + { + vector<int> temp = allContigs.at(i); + for(int j = 0; j < temp.size(); j++) + cout << temp.at(j) << ", "; + cout << endl; + } + cout << endl; +*/} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.h new file mode 100644 index 0000000..f169c00 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/ContigBuilder.h @@ -0,0 +1,49 @@ +/********************************************************************* + * File: ContigBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This ContigBuilder class is used to process contigs + * formed from SA. + *********************************************************************/ + +#ifndef CONTIGBUILDER_H +#define CONTIGBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> + +#include "Util.h" +#include "ConsensusBuilder.h" + +#include "SA.hh" + +using namespace std; + +class ContigBuilder +{ +public: + ContigBuilder(int * order, int ** s, const SA::Problem *pbm); // constructor + ~ContigBuilder() { } // destructor + + void buildContigs(); + void buildConsensus(); + void mergeContigs(); + void mergeTwoContig(int cid1, int cid2); + void print(); + void printOrder(); + vector<string> getPreLayoutFrags(vector<int> order); + vector< vector<int> > getAllContigs() { return allContigs; } +private: + int * fragOrder; // fragment order generated by SA + int ** score; // pointer to score in OverlapDetector class + vector< vector<int> > allContigs; // set of contigs + const SA::Problem *_pbm; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.cpp new file mode 100644 index 0000000..d3ab188 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.cpp @@ -0,0 +1,423 @@ +/*********************************************************************** + * File: LayoutBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file LayoutBuilder.h. + ***********************************************************************/ + +#include "LayoutBuilder.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +LayoutBuilder::LayoutBuilder(const vector<string> & frags) +{ + preLayoutFrags = frags; + fragmentsLayout = new string[frags.size()]; + semiAlign = new AlignedPair[frags.size()-1]; +} + +/************************* + * Purpose: release memory + *************************/ + +LayoutBuilder::~LayoutBuilder() +{ + delete [] semiAlign; + delete [] fragmentsLayout; +} + +/************************************************************ + * Purpose: count number of gaps in front of a given fragment + ************************************************************/ + +int countStartGaps(const string &str) +{ + int count = 0; + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + break; + else + count++; + } + return count; +} + +/************************************************************** + * Purpose: count number of gaps at the end of a given fragment + **************************************************************/ + +int countEndGaps(const string &str) +{ + int count = 0; + for(int i = str.length() - 1; i >= 0; i--) + { + if(str.at(i) != '-') + break; + else + count++; + } + return count; +} + +/********************************************************** + * Purpose: count number of nucleotides in a given fragment + **********************************************************/ + +int countNonGapChar(const string &str) +{ + int count = 0; + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + count++; + } + return count; +} + +/**************************************** + * Purpose: create a given number of gaps + ****************************************/ + +string addGaps(int num) +{ + string gapStr = ""; + for(int i = 0; i < num; i++) + gapStr += "-"; + + return gapStr; +} + +/********************************************************** + * Purpose: count number of middle gaps in a given fragment + **********************************************************/ + +int* findMiddleGaps(const string &str, int count) +{ + int *midGapCounts = new int[count]; + int len = str.length(); + + for(int i = 0; i < count; i++) + { + midGapCounts[i] = 0; + } + + int k = 0; + for(int j = 0; j < len; j++) + { + if(str[j+1] == '-') + { + midGapCounts[k]++; + } + else + k++; + } + + return midGapCounts; +} + +/******************************************** + * Purpose: return the first non-gap position + ********************************************/ + +int findFirstNonGapPos(const string &str) +{ + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + return i; + } + return -1; +} + +/****************************************************************** + * Purpose: compute pairwise alignments for given ordered fragments + ******************************************************************/ + +void LayoutBuilder::findAlignments() +{ + for(int k = 0; k < preLayoutFrags.size()-1; k++) + { + string s = preLayoutFrags[k]; + string t = preLayoutFrags[k+1]; + SGA sga(s, t); + sga.buildMatrix(); + sga.findBestScore(); + sga.align(); + + AlignedPair aResult(sga.align_s, sga.align_t); + semiAlign[k] = aResult; + } +} + +/************************************************************* + * Purpose: insert number of gaps in front of a given fragment + *************************************************************/ + +void LayoutBuilder::insertStartGaps(int id, int numOfGaps) +{ + string temp = fragmentsLayout[id]; + string startGaps = ""; + for(int i = 0; i < numOfGaps; i++) + startGaps += "-"; + fragmentsLayout[id] = startGaps + temp; +} + +/*********************************************************** + * Purpose: insert number of gaps in the middle of fragments + ***********************************************************/ + +void LayoutBuilder::insertMiddleGaps(const string &str1, const string &str2, int k, int prev) +{ + int nonGapCount = countNonGapChar(str1); + int *midGapCounts1 = findMiddleGaps(str1, nonGapCount-1); + int *midGapCounts2 = findMiddleGaps(str2, nonGapCount-1); + + int pos = findFirstNonGapPos(fragmentsLayout[prev]); + + for(int w = 0; w < nonGapCount-1; w++) + { + pos += 1; + if(midGapCounts1[w] != 0 || midGapCounts2[w] != 0) + { + int gapDiff = abs(midGapCounts1[w] - midGapCounts2[w]); + int move = 0; + string gaps = ""; + for(int u = 0; u < gapDiff; u++) + gaps += "-"; + + if(midGapCounts1[w] > midGapCounts2[w]) + { + fragmentsLayout[k].insert(pos, gaps); + move = midGapCounts1[w]; + } + else if (midGapCounts1[w] < midGapCounts2[w]) + { + for(int v = 0; v < k; v++) + fragmentsLayout[v].insert(pos, gaps); + move = midGapCounts2[w]; + } + pos += move; + } + } + delete [] midGapCounts1; + delete [] midGapCounts2; +} + +/*************************************************************** + * Purpose: insert number of gaps at the end of a given fragment + ***************************************************************/ + +void LayoutBuilder::insertEndGaps(int id, int numOfGaps) +{ + string temp = fragmentsLayout[id]; + string endGaps = ""; + for(int i = 0; i < numOfGaps; i++) + endGaps += "-"; + fragmentsLayout[id] = temp + endGaps; +} + +/************************************************************** + * Purpose: extract fragment excluding starting and ending gaps + **************************************************************/ + +string LayoutBuilder::extractMiddleSeq(const string &str) +{ + int startGapCount = countStartGaps(str); + int endGapCount = countEndGaps(str); + int num = str.length() - startGapCount - endGapCount; + return str.substr(startGapCount, num); +} + +/************************************ + * Purpose: check if it is ending gap + ************************************/ + +bool LayoutBuilder::isEndGap(int i, int col) +{ + string middle = extractMiddleSeq(fragmentsLayout[i]); + int firstNonGap = findFirstNonGapPos(fragmentsLayout[i]); + + if(col < firstNonGap || col > firstNonGap + middle.length() - 1) + return true; + else + return false; +} + +/************************************************ + * Purpose: progressively build a fragment layout + ************************************************/ + +void LayoutBuilder::buildLayout() +{ + int j = 0; + fragmentsLayout[j++] = semiAlign[0].s; + fragmentsLayout[j++] = semiAlign[0].t; + + for(int i = 1; i < preLayoutFrags.size()-1; i++) + { + fragmentsLayout[j] = semiAlign[i].t; + + /* handle starting gaps */ + + string s_temp = semiAlign[i].s; + + int s_startGaps = countStartGaps(fragmentsLayout[j-1]); + int stemp_startGaps = countStartGaps(s_temp); + int startGapDiff = abs(s_startGaps - stemp_startGaps); + + if(startGapDiff > 0) + { + if(stemp_startGaps > s_startGaps) + { + for(int m = 0; m < j; m++) + insertStartGaps(m, startGapDiff); + } + else + insertStartGaps(j, startGapDiff); + } + + /* handle middle gaps */ + + string s_middle = extractMiddleSeq(fragmentsLayout[j-1]); + string stemp_middle = extractMiddleSeq(s_temp); + + insertMiddleGaps(s_middle, stemp_middle, j, j-1); + + /* handle end gaps */ + + int s_endGaps = countEndGaps(fragmentsLayout[j-1]); + int stemp_endGaps = countEndGaps(s_temp); + int endGapDiff = abs(s_endGaps - stemp_endGaps); + + if(endGapDiff > 0) + { + if(stemp_endGaps > s_endGaps) + { + for(int m = 0; m < j; m++) + insertEndGaps(m, endGapDiff); + } + else + insertEndGaps(j, endGapDiff); + } + j++; + } +} + +/*********************************************** + * Purpose: find majority of a particular column + ***********************************************/ + +char LayoutBuilder::majorityVote(int col) +{ + int count[5] = { 0, 0, 0, 0, 0 }; + char nucleotide[5] = {'A', 'T', 'C', 'G', '-'}; + char majority1 = 'A'; + char majority2 = 'A'; + + for(int i = 0; i < preLayoutFrags.size(); i++) + { + if(fragmentsLayout[i].at(col) == 'A') + count[0]++; + else if(fragmentsLayout[i].at(col) == 'T') + count[1]++; + else if(fragmentsLayout[i].at(col) == 'C') + count[2]++; + else if(fragmentsLayout[i].at(col) == 'G') + count[3]++; + else if(fragmentsLayout[i].at(col) == '-') + count[4]++; + } + int max = count[0]; + for(int j = 1; j < 5; j++) + { + if(count[j] > max) + { + majority2 = majority1; + max = count[j]; + majority1 = nucleotide[j]; + } + } + bool endGap = true; + if(majority1 == '-') + { + for(int i = 0; i < preLayoutFrags.size() && endGap; i++) + { + if(fragmentsLayout[i].at(col) == '-') + { + endGap = isEndGap(i, col); + } + } + + if(endGap) + return majority2; + } + return majority1; +} + +/*************************************** + * Purpose: find majority of all columns + ***************************************/ + +void LayoutBuilder::findMajority() +{ + int length = fragmentsLayout[0].length(); + + majority = ""; + for(int i = 0; i < length; i++) + { + char c = majorityVote(i); + majority += c; + } +} + +/******************************************** + * Purpose: determine sequence for the layout + ********************************************/ + +void LayoutBuilder::findConsensus() +{ + findMajority(); + consensus = ""; + for(int i = 0; i < majority.length(); i++) + { + if(majority.at(i) != '-') + consensus += majority.at(i); + } +} + +/*************************************************** + * Purpose: print info about all pairs of alignments + ***************************************************/ + +void LayoutBuilder::printAlignments() +{ + for(int j = 0; j < preLayoutFrags.size()-1; j++) + semiAlign[j].printAlign(); +} + +/*********************** + * Purpose: print layout + ***********************/ + +void LayoutBuilder::printLayout() +{ + for(int i = 0; i < preLayoutFrags.size(); i++) + cout << fragmentsLayout[i] << endl; + cout << endl; +} + +/************************** + * Purpose: print consensus + **************************/ + +void LayoutBuilder::printConsensus() +{ + cout << consensus << endl; +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.h new file mode 100644 index 0000000..3e611f5 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/LayoutBuilder.h @@ -0,0 +1,53 @@ +/********************************************************************* + * File: LayoutBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This LayoutBuilder class builds a layout for a contig. + * The contig consists of an ordered set of contiguous + * overlapping fragments. + *********************************************************************/ + +#ifndef LAYOUTBUILDER_H +#define LAYOUTBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> +#include "sga.h" +#include "AlignedPair.h" + +using namespace std; + +class LayoutBuilder +{ +public: + LayoutBuilder(const vector<string> & frags); // constructor + ~LayoutBuilder(); // destructor + void findAlignments(); // compute the alignments using SGA + void buildLayout(); // progressively build layout + void insertStartGaps(int id, int numOfGaps); // insert '-' at the beginning of fragments + void insertMiddleGaps(const string &str1, const string &str2, int k, int prev); + void insertEndGaps(int id, int numOfGaps); // insert '-' at the end of fragments + string extractMiddleSeq(const string &str); + bool isEndGap(int i, int col); + void findMajority(); // find majorities of the layout + char majorityVote(int col); // find majority of a particular column + void findConsensus(); + void printLayout(); + void printConsensus(); + void printAlignments(); + string getConsensus() { return consensus; } +private: + vector<string> preLayoutFrags; // ordered fragments + AlignedPair * semiAlign; // store pairwise alignment result + string * fragmentsLayout; // store layout + string majority; + string consensus; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainLan.cc new file mode 100644 index 0000000..2b937bd --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainLan.cc @@ -0,0 +1,57 @@ +#include "SA.hh" +#include "ContigBuilder.h" +#include <iostream.h> +#include <fstream.h> + +extern int Global_cutoff; + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + Global_cutoff = pbm.cutoff; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainSeq.cc new file mode 100644 index 0000000..488096d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/MainSeq.cc @@ -0,0 +1,48 @@ +#include "SA.hh" +#include "ContigBuilder.h" +#include <iostream.h> +#include <fstream.h> + +extern int Global_cutoff; + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + +//cout << pbm; + Global_cutoff = pbm.cutoff; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Makefile new file mode 100644 index 0000000..275b857 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Makefile @@ -0,0 +1,25 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainScore: SA.req.o SA.pro.o StopCondition.o MainScore.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/DNAFA-instances/pbm.txt res/dna.sa.seq.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.cpp new file mode 100644 index 0000000..49b81ec --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.cpp @@ -0,0 +1,130 @@ +/*********************************************************************** + * File: OverlapDetector.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file OverlapDetector.h. + ***********************************************************************/ + +#include "OverlapDetector.h" + +/************************** + * Purpose: allocate memory + **************************/ + +OverlapDetector::OverlapDetector(int nof):nbOfFrag(nof) +{ + score = new int*[nof]; + for(int i = 0; i < nof; i++) + score[i] = new int[nof]; +} + +/************************** + * Purpose: release memory + **************************/ + +OverlapDetector::~OverlapDetector() +{ + for(int j = 0; j < nbOfFrag; j++) + delete [] score[j]; + delete [] score; +} + +/********************************************************** + * Purpose: construct a score table to store overlap length + * of all possible pair of fragments + **********************************************************/ + +void OverlapDetector::buildScoresTable(vector<string>* fragments, vector<string>* rcFragments) +{ + for(int i = 0; i < nbOfFrag; i++) + { + string rcFrags = rcFragments->at(i); + + for(int j = i+1; j < nbOfFrag; j++) + { + SGA sga1(fragments->at(i), fragments->at(j)); // eg. w1 and w2 + sga1.buildMatrix(); + sga1.findBestScore(); + int score1 = sga1.getBestScore(); + + SGA sga2(rcFrags, fragments->at(j)); // eg. rcw1 and w2 + sga2.buildMatrix(); + sga2.findBestScore(); + int score2 = sga2.getBestScore(); + + if(score2 > score1) // store the larger one + score[j][i] = score[i][j] = -score2; + else + score[j][i] = score[i][j] = score1; + } + } +} + +/*************************** + * Purpose: for testing use + ***************************/ + +void OverlapDetector::readScoreTable() +{ + string inputFile = string(getenv("HOME")) + "/Mallba/ProblemInstances/DNAFA-instances/score.txt"; + ifstream inFile(inputFile.c_str(), ios::in); + if( !inFile ) + { + cout << "\n\t\t*** The file " << inputFile + << " doesn't exist! ***" << endl << endl; + exit(1); + } + +/* char seps[] = " \t\n"; + char oneLine[2000]; + int i = 0; + inFile.getline(oneLine, 2000); + while(inFile.getline(oneLine, 2000)) + { + int j = 0; + char * token = strtok(oneLine, seps); + + while (token != NULL) + { + score[i][j] = atoi(token); + token = strtok(NULL, seps); + j++; + } + i++; + }*/ + for(int i = 0; i < nbOfFrag; i++) + for(int j= 0; j < nbOfFrag; j++) + inFile >> score[i][j]; + inFile.close(); +} + +/************************************ + * Purpose: print overlap score table + ************************************/ + +void OverlapDetector::printScoreTable() +{ +// cout << endl << "*** *** *** *** Overlap Score Table *** *** *** ***" << endl << endl; + +// cout << " "; +// for(int k = 0; k < nbOfFrag; k++) +// cout << setw(5) << setiosflags(ios::right) << "F" << k; + + for(int i = 0; i < nbOfFrag; i++) + { + cout << endl; +// cout << "F" << i << " "; + for(int j = 0; j < nbOfFrag; j++) + { + if(i == j) + cout << setw(5) << setiosflags(ios::right) << "0 "; + else + cout << setw(5) << setiosflags(ios::right) << score[i][j] << " "; + } + } +// cout << endl << endl << "*****************************************************" << endl; +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.h new file mode 100644 index 0000000..a0a0594 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/OverlapDetector.h @@ -0,0 +1,45 @@ +/*************************************************************** + * File: OverlapDetector.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This OverlapDetector class is used to detect the + * similarity of all possible pair of fragments. The + * overlap length between any two fragments is stored + * in a two dimentional array called score. + ***************************************************************/ + +#ifndef OVERLAPDETECTOR_H +#define OVERLAPDETECTOR_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <fstream> +#include <iomanip> +#include <stdlib.h> +#include <string> +#include <vector> + +#include "sga.h" + +using namespace std; + + +class OverlapDetector +{ +public: + OverlapDetector(int nof); // constructor + ~OverlapDetector(); // destructor + void buildScoresTable(vector<string>*, vector<string>*); // build overlap score table for fragments + void readScoreTable(); + void printScoreTable(); + int ** getScoreTable() { return score; } +private: + int ** score; // to store the overlap length of all possible pair of fragments + int nbOfFrag; // Number of Fragments +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.cfg new file mode 100644 index 0000000..739dc52 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +25600 // number of evaluations +256 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +200000 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +200 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.hh new file mode 100644 index 0000000..c8d6914 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.hh @@ -0,0 +1,494 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> +#include <vector> +#include "OverlapDetector.h" + +using namespace std; + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int numOfFragments; // number of fragments^M + double avgLength; // average length of the input fragments^M + int cutoff; // overlap threshold^M + int * fragmentLength; // fragments' lengths^M + vector<string>* fragments; // forward direction of the fragments^M + vector<string>* description; // description of the fragments (Nombre Del Fragmento)^M + vector<string>* rcFragments; // reverse complement of the fragments + OverlapDetector *detector; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness (); + int& fragment(const int index); + int* fragments(); + + private: + int * fragOrder; // an order of an individual ^M + const Problem& _pbm; + + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc new file mode 100644 index 0000000..a89284b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc @@ -0,0 +1,1808 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + /* if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + */ + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc1 b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc1 new file mode 100644 index 0000000..3d95a77 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.pro.cc1 @@ -0,0 +1,1837 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" +#include "ContigBuilder.h" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %d ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + +/* if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1);*/ + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + +cerr << current_best_cost() << endl; + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + { + run(params.max_evaluations()); +// cerr << "Entrado" << endl; +// Solution s(current_best_solution()); +// cerr << s; +// ContigBuilder * builder = new ContigBuilder(s.fragments(), problem.detector->getScoreTable(),&problem); +// builder->buildContigs(); +// builder->mergeContigs(); +// // builder->buildConsensus(); +// delete builder; + + } + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { +cout << "ConstructorA " << endl; + NetStream::init(argc,argv); +cout << "ConstructorB " << endl; + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); +cout << "Constructor " << endl; + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + { + run(params.max_evaluations()); + if(mypid == 0) + { +// cerr << "Entrado" << endl; +// Solution s(current_solution()); +// cerr << s; +// ContigBuilder * builder = new ContigBuilder(s.fragments(), problem.detector->getScoreTable(),&problem); +// builder->buildContigs(); +// builder->mergeContigs(); +// // builder->buildConsensus(); +// delete builder; + } + } + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.req.cc new file mode 100644 index 0000000..153f37c --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/SA.req.cc @@ -0,0 +1,437 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" +#include <math.h> +#include "Util.h" +#include "AdjKeys.h" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():numOfFragments(0),avgLength(0.0),cutoff(0), + fragmentLength(NULL),fragments(NULL),rcFragments(NULL), + description(NULL) + { + } + + ostream& operator<< (ostream& os, const Problem& pbm) + { + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm.cutoff); + + is.getline(buffer,MAX_BUFFER,'\n'); +//cout << buffer; + ifstream f((string(getenv("HOME")) + buffer).c_str()); + + int seqCount = -1; + pbm.fragments = new vector<string>(); + pbm.description = new vector<string>(); + + /* read fragments from input file and store its description in descr[] + and its sequence in sequence[] */ + + char oneLine[2000]; + string sequence; + string upperSeq; + while(f.getline(oneLine, 2000)) + { +//cout << oneLine; + string temp = string(oneLine); + int rightArrow = temp.find_first_of(">"); + if(rightArrow != -1) //rightArrow is found + { + seqCount++; + if(seqCount != 0) + pbm.fragments->push_back(sequence); + int space = temp.find(" ", rightArrow); + pbm.description->push_back(temp.substr(rightArrow+1, space)); + sequence = ""; + } + else //line doesn't start with rightArrow + { + upperSeq = ""; + for(int i = 0; i < temp.length(); i++) + upperSeq += toupper(temp.at(i)); + + sequence.append(upperSeq); + } + } + pbm.fragments->push_back(sequence); + f.close(); + + pbm.numOfFragments = pbm.fragments->size(); + pbm.fragmentLength = new int[pbm.numOfFragments]; + + pbm.rcFragments = new vector<string>(); + + for(int j = 0; j < pbm.numOfFragments; j++) + { + pbm.rcFragments->push_back(Util::rcSequence(pbm.fragments->at(j))); +//cout << pbm.description->at(j) << " " << pbm.fragments->at(j) << " " << pbm.rcFragments->at(j) << endl; + } + + int sumLength = 0; + for(int i = 0; i < pbm.numOfFragments; i++) + { + pbm.fragmentLength[i] = pbm.fragments->at(i).length(); + sumLength += pbm.fragmentLength[i]; + } + pbm.avgLength = (double)sumLength / (double)pbm.numOfFragments; + + pbm.detector = new OverlapDetector(pbm.numOfFragments); +// pbm.detector->buildScoresTable(pbm.fragments, pbm.rcFragments); + pbm.detector->readScoreTable(); +// pbm.detector->printScoreTable(); + + return is; + } + + bool Problem::operator== (const Problem& pbm) const + { + // Falta terminar + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; // F1 +// return minimize; // F2 + } + + Problem::~Problem() + { + delete detector; + delete fragments; + delete rcFragments; + delete description; + delete [] fragmentLength; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),fragOrder(new int[pbm.numOfFragments]) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + if(fragOrder != NULL) delete [] fragOrder; + + fragOrder = new int [_pbm.numOfFragments]; + + for(int i = 0; i < _pbm.numOfFragments; i++) + fragOrder[i] = sol.fragOrder[i]; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + is >> sol.fragOrder[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + os << " " << sol.fragOrder[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + ns << sol.fragOrder[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + ns >> sol.fragOrder[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + if(fragOrder != NULL) delete [] fragOrder; + + fragOrder = new int [_pbm.numOfFragments]; + + for(int i = 0; i < _pbm.numOfFragments; i++) + fragOrder[i] = sol.fragOrder[i]; + + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + for(int i = 0; i < _pbm.numOfFragments; i++) + if(fragOrder[i] != sol.fragOrder[i]) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + int * randNum = new int[_pbm.numOfFragments]; + + for(int k = 0; k < _pbm.numOfFragments; k++) + { + int num = rand_int(0, _pbm.numOfFragments * 2); + randNum[k] = num; + fragOrder[k] = k; + } + + // sort value and store index as fragment order + for(int i = 0; i < _pbm.numOfFragments-1; i++) + { + for(int j = i+1; j < _pbm.numOfFragments; j++) + { + if( randNum[i] > randNum[j]) + { + int temp = randNum[i]; + randNum[i] = randNum[j]; + randNum[j] = temp; + + temp = fragOrder[i]; + fragOrder[i] = fragOrder[j]; + fragOrder[j] = temp; + } + } + } + delete [] randNum; + } + + double Solution::fitness () + { + int ** score = _pbm.detector->getScoreTable(); + // F1 maximization + int fit = 0; + + for(int k = 0; k < _pbm.numOfFragments-1; k++) + { + int i = fragOrder[k]; + int j = fragOrder[k+1]; + + fit += abs(score[i][j]); + } + return (double) fit; + // F2 minimization +/* int fit = 0; + int nof = _pbm.numOfFragments; + + for(int i = 0; i < nof; i++) + { + int m = fragOrder[i]; + for(int j = 0; j < nof; j++) + { + if(i != j) + { + int n = fragOrder[j]; + if((nof<m) || (nof<n) || (m<0) || (n<0)) + { + cout << "Error en indices" << endl; + return infinity(); + } + fit += abs(i-j) * abs(score[m][n]); + } + } + } + return (double)fit; +*/ } + + char *Solution::to_String() const + { + return (char *)fragOrder; + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + + for (int i=0;i<_pbm.numOfFragments;i++) + { + fragOrder[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.numOfFragments * sizeof(int)); + } + + + int& Solution::fragment(const int index) + { + return fragOrder[index]; + } + + + int* Solution::fragments() + { + return fragOrder; + } + + Solution::~Solution() + { + delete [] fragOrder; + } + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + int indsize = sol.pbm().numOfFragments; + int r1 = rand_int(0, indsize-1); + int r2 = rand_int(0, indsize-1); + + while(r2 == r1) + { + if(r1 == indsize-1) r2 = rand_int(0, indsize-2); + else r2 = rand_int(r1, indsize-1); + } + + /* // swap + int temp = sol.fragment(r1); + sol.fragment(r1) = sol.fragment(r2); + sol.fragment(r2) = temp; +*/ + // 2-opt + if(r2 < r1) + { + int temp = r1; + r1 = r2; + r2 = temp; + } + while(r2 > r1) + { + int temp = sol.fragment(r1); + sol.fragment(r1) = sol.fragment(r2); + sol.fragment(r2) = temp; + ++r1; + --r2; + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.cc new file mode 100644 index 0000000..2033972 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (false); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Util.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Util.h new file mode 100644 index 0000000..fcea0d2 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/Util.h @@ -0,0 +1,71 @@ +/************************************************************** + * File: Util.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This Util class consists of utility functions + * used by other classes + **************************************************************/ + +#ifndef UTIL_H +#define UTIL_H + +#include <stdlib.h> +#include <vector> + +using namespace std; + +class Util +{ +public: + /* returns a randomly generated floating point number ranged [min, max] */ +// static double randDouble(double min, double max) +// { +// return (1.0*rand()*(max-min)/RAND_MAX + min); +// } + + /* returns a randomly generated interge number ranged [min, max] */ +// static int randInt(int min, int max) +// { +// return (int)randDouble(min, max); +// } + + /* returns a string that is the reverse of a given DNA sequence */ + static string revSequence(const string &s) + { + string revSeq = s; + int j = 0; + for(int i = s.length()-1; i >= 0; i--) + revSeq[j++] = s.at(i); + + return revSeq; + } + + /* returns a string that is the complement of a given DNA sequence */ + static string complSequence(const string &s) + { + string compSeq = s; + int j = 0; + for(unsigned int i = 0; i < s.length(); i++) + { + if(s.at(i) == 'A') + compSeq[j++] = 'T'; + else if(s.at(i) == 'T') + compSeq[j++] = 'A'; + else if(s.at(i) == 'C') + compSeq[j++] = 'G'; + else if(s.at(i) == 'G') + compSeq[j++] = 'C'; + else + compSeq[j++] = s.at(i); + } + return compSeq; + } + + /* returns a string that is the reverse complement of a given DNA sequence */ + static string rcSequence(const string &s) + { + return complSequence(revSequence(s)); + } +}; +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/list.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/list.h new file mode 100644 index 0000000..46eff2e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/list.h @@ -0,0 +1,300 @@ +/*************************************************************** + * File: list.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This List class is a template class. It builds a + * single linked list of any type of objects. + ***************************************************************/ + +#ifndef LIST_H +#define LIST_H + +#include <assert.h> +#include <stdlib.h> +#include <iostream> +using namespace std; + +template <class T> +struct ListNode +{ + T data; // T could be any type of object + ListNode<T> *next; +}; + +template <class T> +class List1 +{ +public: + ListNode<T>* header; // header is a dummy node + ListNode<T>* current; + int len; // length of the linked list + + List1(); // constructor + ~List1(); // destructor + + List1(const List1<T> & source); // copy constructor + List1<T> & operator=(const List1<T> & source); + void append(const T); // append data at the end of list + void insert(const T); // insert data in order + void insertPtr(const T); // insert pointer type of object in order + void insertFront(const T); // insert data at the beginning of the list + void remove(const T); // delete data from list + void next(); + void prev(); + void reset(); + void clear(); + int length() const { return len; } + bool isEmpty() const; // check whether list is empty + bool isFull() const; // check whether memory is allocated + T value() const; // return content of the data + void printList(); + void printListPtr(); + ListNode<T>* findPrevious(const T); + ListNode<T>* search(const T); +}; + +template <class T> +List1<T>::List1() +{ + header = new ListNode<T>; + header->next = NULL; + current = header; + len = 0; +} + +template <class T> +List1<T>::List1(const List1<T> & source) +{ + header = NULL; + *this = source; +} + +template <class T> +List1<T> & List1<T>::operator=(const List1<T> & source) +{ + if(this != &source) + { + ListNode<T> * current = source.header; + while(current != NULL) + { + insert(current->data); + current = current->pnext; + } + } + return *this; +} + +template <class T> +void List1<T>::clear() +{ + ListNode<T> *tmp; + ListNode<T> *previous = header; + ListNode<T> *traverse = header->next; + + while(traverse != NULL) // release memory from list + { + tmp = traverse; + previous->next = traverse->next; + traverse = traverse->next; + delete tmp; + } + current = header; + len = 0; +} + +template <class T> +List1<T>::~List1() +{ + clear(); + delete header; +} + + +template <class T> +void List1<T>::insert(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + if(len == 0) // no need to traverse + { + newNode->next = current->next; + current->next = newNode; + } + else // need to traverse + { + ListNode<T> * temp = header; + while((temp->next != NULL) && (item < temp->next->data)) + temp = temp->next; + newNode->next = temp->next; + temp->next = newNode; + } + len++; +} + +template <class T> +void List1<T>::insertPtr(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + if(len == 0) // no need to traverse + { + newNode->next = current->next; + current->next = newNode; + } + else // need to traverse + { + ListNode<T> * temp = header; + while((temp->next != NULL) && (*item < *(temp->next->data))) // pointer need dereference + temp = temp->next; + newNode->next = temp->next; + temp->next = newNode; + } + len++; +} + +template <class T> +void List1<T>::insertFront(const T item) +{ + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = header->next; + header->next = newNode; + len++; +} + +template <class T> +void List1<T>::append(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + ListNode<T> *traverse = header; + while(traverse->next != NULL) + traverse = traverse->next; + traverse->next = newNode; + len++; +} + +template <class T> +ListNode<T>* List1<T>::findPrevious(const T target) +{ + ListNode<T> *temp; + + for(temp = header; temp->next != NULL; temp = temp->next) + if(*(temp->next->data) == *target) + return temp; + + return NULL; +} + +template <class T> +void List1<T>::remove(const T target) +{ + if(len != 0) + { + ListNode<T> *p = findPrevious(target); + if(p->next != NULL) + { + ListNode<T> *oldNode = p->next; + p->next = p->next->next; + delete oldNode; + len--; + } + } +} + +template <class T> +void List1<T>::next() +{ + current = current->next; +} + +template <class T> +void List1<T>::prev() +{ + if(len > 1) + { + ListNode<T>* tmp = header; + while(tmp->next != current) + tmp = tmp->nect; + + current = tmp; + } +} + +template <class T> +void List1<T>::reset() +{ + current = header; +} + +template <class T> +bool List1<T>::isEmpty() const +{ + return (len == 0); +} + +template <class T> +bool List1<T>::isFull() const +{ + ListNode<T> *tmp = new ListNode<T>; + if(tmp == NULL) + return true; + else + { + delete tmp; + return false; + } +} + +template <class T> +T List1<T>::value() const +{ + return current->next->data; +} + +template <class T> +ListNode<T>* List1<T>::search(const T target) +{ + ListNode<T> *temp; + + for(temp = header->next; temp != NULL; temp = temp->next) + if((*target) == *(temp->data)) + return temp; + + return NULL; +} + +template <class T> +void List1<T>::printList() +{ + cout << endl; + for(int i = 0; i < len; i++) + { + cout << value(); + next(); + } + reset(); +} + +template <class T> +void List1<T>::printListPtr() +{ + cout << endl; + for(int i = 0; i < len; i++) + { + cout << *(value()); // pointer need dereference + next(); + } + reset(); +} + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/pgfileLan new file mode 100644 index 0000000..d8a0011 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/pgfileLan @@ -0,0 +1,3 @@ +localhost 0 ~/Mallba/rep/SA/dnafa/MainLan +localhost 1 ~/Mallba/rep/SA/dnafa/MainLan +localhost 1 ~/Mallba/rep/SA/dnafa/MainLan diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/scp.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/scp.h new file mode 100644 index 0000000..86960d6 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/scp.h @@ -0,0 +1,53 @@ +/******************************************************************* + * File: scp.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This SubConsensusPair class is used to create + * SubConsensusPair objects for ConsensusBuilder class + *******************************************************************/ + +#ifndef SCP_H +#define SCP_H + +#include <iostream> + +using namespace std; + +class SubConsensusPair +{ +public: + int cid1; // first consensus's ID + int cid2; // second consensus's ID + int score; // overlap score between two consensuses + + SubConsensusPair() { } // default constructor + SubConsensusPair(int id1, int id2, int s) // user defined constructor + { + cid1 = id1; + cid2 = id2; + score = s; + } + virtual ~SubConsensusPair() { } // destructor + + bool operator<(const SubConsensusPair& source) const + { + if(score < source.score) + return true; + else + return false; + } + /* overload operator<< for printing the contents of a SubConsensusPair object */ + friend ostream& operator<<(ostream& os, const SubConsensusPair &info) + { + os << "(" << info.cid1 << ", " << info.cid2 << ", " << info.score << ")" << endl; + return os; + } +}; + + /* overload operator<< for printing the contents of a SubConsensusPair object */ + //ostream& operator<<(ostream& os, const SubConsensusPair& info) + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.cpp b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.cpp new file mode 100644 index 0000000..29d740b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.cpp @@ -0,0 +1,256 @@ +/*********************************************************************** + * File: sga.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file sga.h. + ***********************************************************************/ + +#include "sga.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +SGA::SGA(const string &is, const string &it) +{ + g = -2; // gap penalty = -2 + s = is; + t = it; + m = s.length(); + n = t.length(); +// /**/ cout << "\t size " << m+1 << " x " << n+1 << endl; + bestScore = 0; +} + +/************************* + * Purpose: release memory + *************************/ + +SGA::~SGA() +{ +} + + +/******************************************************* + * Purpose: Build a score matrix to store the scores of + * pairwise semiglobal alignment + *******************************************************/ + +void SGA::CalculateBest(int i, int j, int score) +{ +//cout << "(" << i<<","<< j<<","<<score<<")"<<endl; + if(j == n) + { + if((score == n) && (score > bestScore)) // ------- + { // --- + bestScore = score; + overlapType = 1; + } + else if((score == i) && (score > bestScore)) // ------- + { // ------- + bestScore = score; + overlapType = 2; + } + } + + if(i == m) + { + if((score == m) && (score > bestScore)) // --- + { // --------- + bestScore = score; + overlapType = 3; + } + else if((score == j) && (score > bestScore)) // ------- + { // ------- + bestScore = score; + overlapType = 4; + } + } +} + +void SGA::buildMatrix() +{ + // Primero la mitad superior + int i,j,k; + int score; + bestScore = 0; + overlapType = 3; + for(k = 1; k <= m; k++) + { + score = 0; + i = k; + j = 1; + while((j <=n) && (i <=m)) + { + if(p(i,j) == 1) + score = score + 1; + else + score = 0; + j++; + i++; + } + i--;j--; + CalculateBest(i,j,score); + } + + for(k = 2; k <= n; k++) + { + score = 0; + j = k; + i = 1; + while(j <=n && i <=m) + { + if(p(i,j) == 1) + score = score + 1; + else + score = 0; + j++; + i++; + } + i--;j--; + CalculateBest(i,j,score); + } +} + +/*************************** + * match score = 1 + * mismatch score = -1 + ***************************/ + +int SGA::p(int i, int j) +{ + if (s[i-1] == t[j-1]) // match + return 1; + else + return -1; +} + +/**************************************************** + * Purpose: find the maximum number of x, y, and z + ****************************************************/ + +int SGA::max(int x, int y, int z) +{ + int temp = x; + if (x < y) + temp = y; + if (temp < z) + temp = z; + return temp; +} + +/******************************************************************** + * Purpose: find the best score for the pairwise semiglobal alignment + ********************************************************************/ + +void SGA::findBestScore() +{ +} + + +/********************************************************************** + * Purpose: Align the two sequence starting from the the row and column + * with the best score + **********************************************************************/ + +void SGA::align() +{ + int i; + int start; +//cout << s << endl << t << endl << bestScore << " " << overlapType << endl; +//exit(-1); + string preGaps = ""; + string postGaps = ""; + if((start = s.find(t)) != string::npos) // t is substring of s + { + align_s = s; + for(i = 0; i < start; i++) + preGaps += "-"; + align_t = preGaps + t; + + for(i = start+bestScore; i < m; i++) + postGaps += "-"; + align_t += postGaps; + } + else if((start = t.find(s)) != string::npos) // s is substring of t + { + align_t = t; + for(i = 0; i < start; i++) + preGaps += "-"; + align_s = preGaps + s; + + for(i = start+bestScore; i < n; i++) + postGaps += "-"; + align_s += postGaps; + } + else if(overlapType == 4) + { + int preNumGaps = m - bestScore; + for(int i = 0; i < preNumGaps; i++) + preGaps += "-"; + align_t = preGaps + t; + + int postNumGaps = align_t.length() - m; + for(int j = 0; j < postNumGaps; j++) + postGaps += "-"; + align_s = s + postGaps; + } + else + { + int preNumGaps = n - bestScore; + for(int i = 0; i < preNumGaps; i++) + preGaps += "-"; + align_s = preGaps + s; + + int postNumGaps = align_s.length() - n; + for(int j = 0; j < postNumGaps; j++) + postGaps += "-"; + align_t = t + postGaps; + } +} + +/************************************************************ + * Purpose: Print the score matrix for the pairwise alignment + ************************************************************/ + +void SGA::printMatrix() +{ +/* for (int i = 0; i <= m; i++) + { + cout << endl; + for (int j = 0; j <= n; j++) + { + printf("%3d", score[i][j]); + } + } + cout << endl << endl; + cout << "The best score is: " << bestScore << endl << endl;*/ +} + +/*************************************** + * Purpose: Print the pairwise alignment + ***************************************/ + +void SGA::printAlign() +{ + cout << align_s << endl; + cout << align_t << endl << endl; +} + +/******************************* + * Purpose: Print Info for debug + *******************************/ +void SGA::printInfo() +{ + cout << "m = " << m << " n = " << n << " g = " << g + << " bestRow = " << bestRow << " bestCol = " << bestCol << " bestscore = " << bestScore + << endl; + cout << "s = " << align_s << " t = " << align_t << endl; + +// printMatrix(); +} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.h b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.h new file mode 100644 index 0000000..1cf336d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/dnafa/sga.h @@ -0,0 +1,52 @@ +/*************************************************************** + * File: sga.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This SGA class is used to do pairwise alignment + * between two fragments + ***************************************************************/ + +#ifndef SGA_H +#define SGA_H + +#include <iostream> +#include <string> +using namespace std; + +class SGA +{ +public: + string align_s; // to store sequence s after alignment + string align_t; // to store sequence t after alignment + + SGA() {} // default constructor + SGA(const string &is, const string &it); // user defined constructor + ~SGA(); // destructor + void buildMatrix(); + int p(int i, int j); + void align(); + void findBestScore(); + void printMatrix(); + void printAlign(); + void printInfo(); + int getBestRow() { return bestRow; } + int getBestCol() { return bestCol; } + int getBestScore() { return bestScore; } +private: + int max(int x, int y, int z); + void CalculateBest(int i, int j, int score); + string s, t; + int g; // gap + int m; // length of s + int n; // length of t + int bestRow; // the row containning best score + int bestCol; // the column containing best score + int bestScore; // the best score of the semiglobal alignment +// int ** score; // to store the scores for pairwise alignment + int overlapType; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Config.cfg new file mode 100644 index 0000000..2d6daf7 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/MAXSAT-instances/sat1.txt +res/sat1.sa.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Makefile new file mode 100644 index 0000000..0ffc8d9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/MAXSAT-instances/sat1.txt res/sat1.sa.seq.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.cfg new file mode 100644 index 0000000..0aef72f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +500 // number of evaluations +10 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.hh new file mode 100644 index 0000000..26c7864 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.hh @@ -0,0 +1,493 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem(); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + double infinity() const; + + int numvar() const; + int numclause() const; + int lenclause() const; + int *clause(const int i) const; + + + private: + + int _numvar; + int _numclause; + int _lenclause; + int ** _clauses; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness (); + unsigned int size() const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.req.cc new file mode 100644 index 0000000..f3554e7 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/SA.req.cc @@ -0,0 +1,364 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_numvar(0),_numclause(0),_clauses(NULL),_lenclause(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of variables " << pbm._numvar + << endl << endl << "Number of clauses " << pbm._numclause + << endl << endl << "Length of clauses " << pbm._lenclause + << endl << endl + << " Clauses: " << endl; + + for (int i=0;i<pbm._numclause;i++) + { + os << "\t clause " << i << "\t "; + for(int j = 0; j < pbm._lenclause; j++) + os << pbm._clauses[i][j] << " "; + os << endl; + } + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + int l; + int n; + is >> pbm._numvar >> pbm._numclause >> pbm._lenclause; + + n = pbm._lenclause; + // read clauses + pbm._clauses = new int*[pbm._numclause]; + + for (int i = 0; i < pbm._numclause; i++) + { + pbm._clauses[i] = new int[n]; + for(int j = 0; j < n;j++) + { + is >> l; + pbm._clauses[i][j] = l; + } + is >> l; + } + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + int n; + _numvar=pbm.numvar(); + for(int i = 0; i < _numclause;i++) + delete [] _clauses[i]; + delete [] _clauses; + + _numclause = pbm.numclause(); + n = _lenclause = pbm.lenclause(); + + _clauses = new int *[_numclause]; + + for(int i = 0; i < pbm._numclause;i++) + { + _clauses[i] = new int [n]; + for(int j = 0; j < n ; j++) + _clauses[i][j] = pbm._clauses[i][j]; + } + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_numvar!=pbm.numvar()) return false; + for (int i = 0; i < _numclause; i++) + for(int j = 0; j < _lenclause;j++) + if ( _clauses[i][j] != pbm._clauses[i][j]) + return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + double Problem::infinity() const + { + double one=1.0; + double zero=0.0; + return 0.0 - one/zero; + } + + int Problem::numvar() const + { + return _numvar; + } + + int Problem::numclause() const + { + return _numclause; + } + + int Problem::lenclause() const + { + return _lenclause; + } + + int *Problem::clause(const int i) const + { + return _clauses[i]; + } + + Problem::~Problem() + { + for(int i = 0;i < _numclause;i++) + delete [] _clauses[i]; + + delete [] _clauses; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.numvar()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().numvar();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().numvar();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var = sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.numvar();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () + { + double fitness = 0.0; + int acum = 0; + + for(int i = 0; i < _pbm.numclause(); i++) + { + int *rl = _pbm.clause(i); + acum = 0; + for(int j = 0; (j < _pbm.lenclause()) && (acum != 1);j++) + { + if( ((rl[j] < 0) && (_var[(int)abs(rl[j])-1] == 0)) + || ((rl[j] > 0) && (_var[rl[j]-1] == 1)) ) + acum = 1; + } + fitness += acum; + } + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.numvar();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.numvar() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().numvar();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.cc new file mode 100644 index 0000000..dcd0513 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.numclause()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/pgfileLan new file mode 100644 index 0000000..a681b21 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/maxsat/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Config.cfg new file mode 100644 index 0000000..87d424d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.sa.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Makefile new file mode 100644 index 0000000..82415bb --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/ONEMAX-instances/onemax10.txt res/om10.sa.seq.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.cfg new file mode 100644 index 0000000..b6c9399 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +500 // number of evaluations +5 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.hh @@ -0,0 +1,488 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int dimension() const; + double infinity() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.req.cc new file mode 100644 index 0000000..a327cb3 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/SA.req.cc @@ -0,0 +1,286 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + double Problem::infinity() const + { + double one=1.0; + double zero=0.0; + return 0.0 - one/zero; + } + + Problem::~Problem() + { + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () const + { + double fitness = 0.0; + + for (int i=0;i<_var.size();i++) + fitness += _var[i]; + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.dimension()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/pgfileLan new file mode 100644 index 0000000..fa76afb --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/onemax/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileLan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileLan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileWan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileWan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/pgfileWan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Config.cfg new file mode 100644 index 0000000..c8bac1a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/RND-instances/rnd149.txt +res/rnd149.sa.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Makefile new file mode 100644 index 0000000..b15a6cd --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/RND-instances/rnd149.txt res/rnd149.sa.seq.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.cfg new file mode 100644 index 0000000..1dbac85 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +5000 // number of evaluations +50 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.hh @@ -0,0 +1,488 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int dimension() const; + double infinity() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.req.cc new file mode 100644 index 0000000..1702a43 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/SA.req.cc @@ -0,0 +1,385 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +//Parámetros para RND ------------------------------------------------------------- + +#define GRID_SIZE_X 287 //Artificial grid horizontal size. +#define GRID_SIZE_Y 287 //Artificial grid vertical size. +#define GRID_SIZE 82369 //Total grid size. +#define TRANS_NUMB 59 //Number of transmiters used. +#define TRANS_TOTAL 349 //Number of total transmiters. + //49 transmiters distributed regulary... + //... the rest is distributed randomly. + +#define RANGE 20 //Transmiter cover range (square area) + +//------------------------------------------------------------------------------------------------------- +#define TARGET_FITNESS 204.08 //Fitness to be achieved in current trial +//------------------------------------------------------------------------------------------------------- + + +#define MAX_FIT 204.08 //Fitness for optimum solution. +#define AVG_B -4.878 //Coef. for linear penalty of fitness value ... +#define AVG_A 4.878 // ... depending on avg. and dev. overlapping. +#define DEV_B 0.0 +#define DEV_A 2.404 + +//--------------------------------------------------------------------------------- + +skeleton SA { + + + + + //Array ------------------------------------------------------------------ + + static short int trans_location[TRANS_TOTAL*2]= + {20,20, 61,20, 102,20, 143,20, 184,20, 225,20, 266,20, + 20,61, 61,61, 102,61, 143,61, 184,61, 225,61, 266,61, + 20,102, 61,102, 102,102, 143,102, 184,102, 225,102, 266,102, + 20,143, 61,143, 102,143, 143,143, 184,143, 225,143, 266,143, + 20,184, 61,184, 102,184, 143,184, 184,184, 225,184, 266,184, + 20,225, 61,225, 102,225, 143,225, 184,225, 225,225, 266,225, + 20,266, 61,266, 102,266, 143,266, 184,266, 225,266, 266,266, + + 169,180, 180,161, 160,233, 57,156, 158,145, 138,151, 160,32, + 165,36, 228,111, 251,181, 110,130, 286,19, 96,183, 91,133, + 88,74, 93,56, 35,273, 152,198, 142,181, 37,117, 271,193, + 49,109, 104,119, 110,54, 58,160, 135,204, 220,172, 4,141, + 160,244, 210,14, 36,37, 98,3, 134,226, 197,109, 101,17, + 112,230, 169,126, 215,44, 206,27, 18,90, 14,272, 40,134, + 160,150, 58,216, 170,37, 252,185, 246,142, 154,247, 180,128, + 188,55, 207,201, 134,15, 31,111, 166,34, 206,116, 223,261, + 94,48, 227,179, 24,250, 46,26, 159,245, 279,56, 235,43, + 195,166, 165,241, 203,9, 190,73, 20,91, 25,200, 211,255, + 260,199, 262,66, 283,120, 16,76, 38,112, 201,172, 144,1, + 273,282, 230,285, 222,240, 70,132, 240,40, 202,147, 35,175, + 24,41, 4,120, 88,114, 23,104, 274,142, 83,230, 281,265, + 248,58, 140,42, 136,185, 17,2, 9,42, 156,115, 216,32, + 242,104, 221,224, +241,113,224,229,261,56,96,220,79,158,137,180,104,147,273,262,182,205,40,174, +4,69,39,230,44,115,37,31,286,62,147,240,175,84,182,150,141,279,83,221, +151,220,114,255,81,101,231,263,20,272,150,24,55,190,255,100,18,5,131,18, +68,278,258,244,76,154,107,218,147,191,152,11,125,267,267,206,81,211,183,101, +197,47,126,252,237,94,65,256,100,197,274,168,188,246,126,265,114,233,196,261, +138,61,272,264,42,252,183,123,177,80,225,88,128,64,53,79,159,119,48,260, +29,36,142,218,282,268,196,109,215,105,84,66,167,70,43,210,36,227,47,213, +21,272,15,149,50,68,228,210,188,277,183,218,26,38,149,22,20,58,132,235, +164,216,14,45,286,58,255,36,286,15,249,20,1,264,170,51,46,112,262,235, +103,158,166,129,197,28,152,217,87,284,165,251,214,180,10,214,239,265,250,238, +281,213,259,282,191,142,47,238,255,22,186,71,180,65,201,90,94,66,21,181, +64,186,146,278,80,156,206,32,135,170,271,129,96,243,124,0,98,171,239,67, +193,138,138,87,204,52,178,11,118,199,193,183,99,52,174,179,209,94,212,58, +264,196,187,73,152,25,74,251,196,26,31,103,165,170,191,82,222,82,94,54, +282,1,237,95,54,125,275,263,219,200,34,196,110,222,270,262,247,58,227,157, +85,259,261,250,142,165,46,78,248,141,133,243,142,83,51,196,208,39,173,141, +240,207,51,63,143,34,39,103,93,267,260,178,240,234,142,96,113,189,174,74, +43,20,30,185,104,82,95,26,122,268,167,76,189,218,139,45,253,179,148,59, +160,122,238,113,70,93,209,183,282,97,257,39,117,1,224,222,84,32,248,206, +14,128,283,203,60,136,248,26,28,109,86,188,232,37,14,15,131,224,198,127}; + //Transmiters location array + + static short int grid[GRID_SIZE]; + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + Problem::~Problem() + {} + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () const + { + register int x,y,x1,y1,k; + double covered_points=0.0, cover_rate=0.0, fitness=0.0,alfa=2.0; + int used_trans; + + for (k=0;k<GRID_SIZE;k++) // Initializing the grid + grid[k]=0; + + + used_trans=0; // Updating covered points in the grid according ... + for (k=0;k<_var.size();k++) // with transmiter locations and calculating ... + { // covered points. + if (_var[k]!=0.0) + { + used_trans++; + x=trans_location[k*2]; + y=trans_location[k*2+1]; + for (x1=x-RANGE;x1<=x+RANGE;x1++) + for (y1=y-RANGE;y1<=y+RANGE;y1++) + if ((x1>=0)&(y1>=0)&(x1<GRID_SIZE_X)&(y1<GRID_SIZE_Y)) + { + grid[x1*GRID_SIZE_X+y1]++; + if (grid[x1*GRID_SIZE_X+y1]==1) covered_points++; + } + } + } + + cover_rate =(double) (100.0 * covered_points) / (GRID_SIZE); + fitness = (cover_rate * cover_rate )/used_trans; + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.dimension()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/pgfileLan new file mode 100644 index 0000000..d85e66e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/rnd/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Config.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Config.cfg new file mode 100644 index 0000000..510e26d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/VRP-instances/vrpnc1.txt +res/vrp1.sa.lan.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainLan.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainSeq.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Makefile new file mode 100644 index 0000000..cb3ba14 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/VRP-instances/vrpnc1.txt res/vrp1.sa.seq.txt diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.cfg b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.cfg new file mode 100644 index 0000000..eed6739 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +1000 // number of evaluations +10 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +1001 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.hh new file mode 100644 index 0000000..845bb53 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.hh @@ -0,0 +1,499 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int nCustomers() const; + int capacity() const; + double maxRouteTime() const; + double bestCost() const; + double distance(const int i, const int j) const; + int demand(const int i) const; + int service_time() const; + + private: + void genDistances(int *x,int *y); + + int _nCustomers; + int _capacity; + double **_distance; + int _service_time; + double _maxRouteTime; + double _bestCost; + int *_demand; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int & pos(const int index); + Rarray<int> & routes(); + void print(); + + private: + Rarray<int> _routes; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.pro.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.req.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.req.cc new file mode 100644 index 0000000..c14f23a --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/SA.req.cc @@ -0,0 +1,527 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + +// Problem --------------------------------------------------------------- + Problem::Problem ():_nCustomers(0),_capacity(0),_distance(NULL), + _demand(NULL),_service_time(0),_maxRouteTime(0.0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << " Vehicle capacity: " << pbm._capacity + << endl << " Number of Customers: " << pbm._nCustomers << endl + << " Service time: " << pbm._service_time << endl + << " Max Time for any route: " << pbm._maxRouteTime << endl + << " Distances: " << endl; + + for(int i = 0; i < (pbm._nCustomers + 1) ; i++) + { + for(int j = 0; j < pbm._nCustomers; j++) + os << " " << pbm.distance(i,j); + os << endl; + } + + os << endl << " Demand for each customer: " << endl; + + for(int i = 0; i < (pbm._nCustomers + 1) ; i++) + { + os << " " << i << "\t" << pbm._demand[i] << endl; + } + + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int *x; + int *y; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d %lf %d %lf",&pbm._nCustomers,&pbm._capacity,&pbm._maxRouteTime,&pbm._service_time,&pbm._bestCost); + + if( ((pbm._distance = new double *[pbm._nCustomers + 1]) == NULL) + || ((pbm._demand = new int[pbm._nCustomers + 1]) == NULL) + || ((x = new int[pbm._nCustomers + 1]) == NULL) + || ((y = new int[pbm._nCustomers + 1]) == NULL)) + show_message(7); + + // Read depot coordenates + if( ((pbm._distance[0] = new double[pbm._nCustomers+1]) == NULL)) + show_message(7); + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d",&(x[0]),&(y[0])); + pbm._demand[0] = 0; + + // Read customers coordenates + for(int i = 1; i < (pbm._nCustomers + 1); i++) + { + if( ((pbm._distance[i] = new double[pbm._nCustomers+1]) == NULL)) + show_message(7); + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d %d", &(x[i]),&(y[i]),&(pbm._demand[i])); + } + + pbm.genDistances(x,y); + + delete [] x; + delete [] y; + + return is; + } + + void Problem::genDistances(int *x,int *y) + { + for(int i = 0; i < (_nCustomers + 1); i++) + for(int j = 0; j < (_nCustomers +1) ; j++) + _distance[i][j] = sqrt( pow( (double) (x[j] - x[i]),2 ) + + pow( (double) (y[j] - y[i]),2 ) ) + _service_time ; + } + + Problem& Problem::operator= (const Problem& pbm) + { + if(_distance != NULL) + { + for(int i= 0;i < (_nCustomers+1); i++) + if(_distance[i] != NULL) delete [] _distance[i]; + delete [] _distance; + } + + if(_demand != NULL) delete [] _demand; + + if( ((_distance = new double*[pbm._nCustomers]) == NULL) + || ((_demand = new int[pbm._nCustomers + 1]) == NULL)) + show_message(7); + + _nCustomers = pbm.nCustomers(); + _capacity = pbm.capacity(); + _service_time = pbm.service_time(); + _maxRouteTime = pbm.maxRouteTime(); + + for(int i = 0; i < (_nCustomers+1); i++) + { + _demand[i] = pbm.demand(i); + + if( ((_distance[i] = new double[_nCustomers+1]) == NULL)) + show_message(7); + + for(int j = 0; j < (_nCustomers+1); i++) + { + _distance[i][j] = pbm.distance(i,j); + } + } + + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if( (_maxRouteTime != pbm.maxRouteTime()) || (_nCustomers != pbm.nCustomers()) + || (_capacity != pbm.capacity()) || (_service_time != pbm.service_time())) + return false; + + for(int i = 0; i < (_nCustomers+1); i++) + { + if(_demand[i] != pbm.demand(i)) + return false; + + for(int j = 0; j < (_nCustomers+1); i++) + { + if(distance(i,j) != pbm.distance(i,j)) return false; + } + } + + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + double Problem::maxRouteTime() const + { + return _maxRouteTime; + } + + double Problem::bestCost() const + { + return _bestCost; + } + + int Problem::nCustomers() const + { + return _nCustomers; + } + + int Problem::capacity() const + { + return _capacity; + } + + double Problem::distance(const int i, const int j) const + { + return _distance[i][j]; + } + + int Problem::demand(const int i) const + { + return _demand[i]; + } + + int Problem::service_time() const + { + return _service_time; + } + + Problem::~Problem() + { + if(_distance != NULL) + { + for(int i= 0;i < (_nCustomers+1); i++) + if(_distance[i] != NULL) delete [] _distance[i]; + delete [] _distance; + } + + if(_demand != NULL) delete [] _demand; + + } + +// Solution -------------------------------------------------------------- + Solution::Solution (const Problem& pbm):_pbm(pbm),_routes(pbm.nCustomers()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers(); i++) + { + is >> sol._routes[i]; + } + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers(); i++) + { + os << (sol._routes[i]<10?" ":"") << sol._routes[i] << " "; + } + + return os; + } + + void Solution::print() + { + int ultimo = 0; + double dist = 0.0; + int cap = _pbm.capacity(); + + register int c_actual; + register int i = 0; + + int nRoute = 1; + + cout << " Ruta " << nRoute << " = 0 "; + while(i < _pbm.nCustomers()) + { + c_actual = _routes[i]; + + if( ((dist + _pbm.distance(ultimo,c_actual) + _pbm.distance(c_actual,0)) > _pbm.maxRouteTime()) + || (( cap - _pbm.demand(c_actual)) < 0) + // add in version 1.0.1 + || ((_pbm.distance(ultimo,0) + _pbm.distance(0,c_actual)) < _pbm.distance(ultimo,c_actual)) + ) + { + nRoute++; + cout << "0 -> dist = " << (dist + _pbm.distance(ultimo,0)) << " capacidad sobra = " << cap + << endl << "Ruta " << nRoute << " = 0 "; + ultimo = 0; + dist = 0.0; + cap = _pbm.capacity(); + } + else + { + dist += _pbm.distance(ultimo,c_actual); + cap -= _pbm.demand(c_actual); + ultimo = c_actual; + cout << ultimo << " "; + i++; + } + } + + cout << "0 -> dist = " << (dist + _pbm.distance(ultimo,0)) << " capacidad sobra = " << cap + << endl; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers();i++) + ns << sol._routes[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers();i++) + ns >> sol._routes[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _routes = sol._routes; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + int aux,ind1,ind2; + + int max = _pbm.nCustomers(); + + for(int i = 0; i < max; i++) + _routes[i] = i+1; + + cout << endl; + + for(int i=0;i< (max*5) ; i++) + { + ind1 = rand_int(0,max-1); + ind2 = rand_int(0,max-1); + + aux = _routes[ind1]; + _routes[ind1] = _routes[ind2]; + _routes[ind2] = aux; + } + } + + double Solution::fitness () const + { + double fitness = 0.0; + int ultimo = 0; + double dist = 0.0; + int cap = _pbm.capacity(); + + register int c_actual; + register int i = 0; + + while(i < _pbm.nCustomers()) + { + c_actual = _routes[i]; + + if( ((dist + _pbm.distance(ultimo,c_actual) + _pbm.distance(c_actual,0)) > _pbm.maxRouteTime()) + || (( cap - _pbm.demand(c_actual)) < 0) + // Add on version 1.0.1 + // New constrains: cost( Route + actual) < cost( new Route(actual)) + || ((_pbm.distance(ultimo,0) + _pbm.distance(0,c_actual)) < _pbm.distance(ultimo,c_actual)) + ) + { + fitness += dist + _pbm.distance(ultimo,0); + ultimo = 0; + dist = 0.0; + cap = _pbm.capacity(); + } + else + { + dist += _pbm.distance(ultimo,c_actual); + cap -= _pbm.demand(c_actual); + ultimo = c_actual; + i++; + } + } + + fitness += dist + _pbm.distance(ultimo,0); + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_routes.get_first(); + } + + void Solution::to_Solution(char *_routes_) + { + int *ptr=(int *)_routes_; + + for (int i=0;i<_pbm.nCustomers();i++) + { + _routes[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return ( _pbm.nCustomers() * sizeof(int)); + } + + int & Solution::pos(const int index) + { + return _routes[index]; + } + + + Rarray<int>& Solution::routes() + { + return _routes; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + Solution aux(sol); + const int max = sol.pbm().nCustomers(); + float fit = sol.fitness(); + float fit_a; + Direction d = sol.pbm().direction(); + + for(int i = 0; i < max; i++) + for(int j = i+1; j < max; j++) + { + aux.routes().invert(i,j); + fit_a = aux.fitness(); + if( ((d == minimize) && (fit_a < fit)) + || ((d == minimize) && (fit_a > fit) && (rand01() < 0.3)) + || ((d == maximize) && (fit_a > fit)) + || ((d == maximize) && (fit_a < fit) && (rand01() < 0.3))) + { + fit = fit_a; + sol = aux; + } + else aux = sol; + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.cc b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.cc new file mode 100644 index 0000000..e5a2279 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((double)solver.current_best_cost()==pbm.bestCost()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.hh b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/pgfileLan b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/pgfileLan new file mode 100644 index 0000000..1c419a1 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/rep/SA/vrp/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/Makefile b/ProyectoFinal/AlgoritmoGenetico/malva/src/Makefile new file mode 100644 index 0000000..b6d64fb --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/Makefile @@ -0,0 +1,14 @@ +include ../environment + +OBJS = States.o netstream.o + +all: $(OBJS) + +States.o: States.cc States.hh + $(CXX) $(CPPFLAGS) States.cc -c + +netstream.o: netstream.cc netstream.hh + $(CXX) $(CPPFLAGS) netstream.cc -c + +clean: + rm -f *.o *~ *% diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/Matrix.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/Matrix.hh new file mode 100644 index 0000000..cc30ae7 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/Matrix.hh @@ -0,0 +1,337 @@ +/***************************************************************************** +*** *** +*** Este fichero decribe el template Matrix, para el manejo de matrices. *** +*** Tambien permite el manejo de vectores, los que trata como matrices cuya*** +*** primera dimension es 1. *** +*** *** +*****************************************************************************/ +#ifndef _MATRIX +#define _MATRIX + +#include "Messages.h" +#include <assert.h> + +template <class T> class Matrix +{ + private: + T *_matrix; + T nulo,neutro,inverso; + int _dimX,_dimY; + + public: + Matrix() + { + _dimX = _dimY = 0; + _matrix = NULL; + } + + Matrix(const int x,const int y,const T nulo = 0.0,const T neutro = 1.0,const T inverso = -1.0) + { + assert(x >= 1); + assert(y >= 1); + + int k = 0; + + _dimX = x; + _dimY = y; + + this->nulo = nulo; + this->neutro = neutro; + this->inverso = inverso; + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < x; i++) + { + for(int j = 0; j < y ; j++) + { + _matrix[k] = (i!=j?nulo:neutro); + k++; + } + + } + } + + Matrix(const int y,const T nulo = 0.0,const T neutro = 1.0,const T inverso = -1.0) + { + assert(y >= 1); + + _dimX = 1; + _dimY = y; + + this->nulo = nulo; + this->neutro = neutro; + this->inverso = inverso; + + _matrix = new T [_dimY]; + if(!_matrix) show_message(7); + + _matrix[0] = neutro; + for(int j = 1; j < y ; j++) + _matrix[j] = nulo; + } + + Matrix(const Matrix<T> &m) + { + + _dimX = m.dimX(); + _dimY = m.dimY(); + + nulo = m.nulo; + neutro = m.neutro; + inverso = m.inverso; + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < (_dimX*_dimY); i++) + { + _matrix[i] = m[i]; + } + } + + + ~Matrix() + { + remove(); + } + + T &operator()(const int x,const int y) const + { + if((x >= _dimX) || (y >= _dimY)) + show_message(14); + + return (T&)(*(_matrix + (x*_dimX) + y)); + } + + T &operator[](const int y) const + { + if(y >= (_dimX*_dimY)) + show_message(14); + + return (T&)(*(_matrix + y)); + } + + T &operator()(const int y) const + { + if(y >= (_dimX*_dimY)) + show_message(14); + + return (T&)(*(_matrix + y)); + } + + Matrix<T> &operator=(const Matrix<T> &m) + { + remove(); + + _dimX = m.dimX(); + _dimY = m.dimY(); + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < (_dimX*_dimY); i++) + { + _matrix[i] = m[i]; + } + + return (*this); + } + + bool operator==(const Matrix<T> &m) const + { + if((_dimX != m.dimX()) || (_dimY != m.dimY())) + return false; + + for(int i = 0; i < (_dimX*_dimY); i++) + if(_matrix[i] != m[i]) return false; + + return true; + } + + bool operator!=(const Matrix<T> &m) const + { + return !((*this) == m); + } + + Matrix<T> operator*(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimY?0:_dimX); + int y = (x!=0?m.dimY():0); + T acum = nulo; + + Matrix<T> res(x,y); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < m.dimY(); j++) + { + acum = nulo; + for( int k = 0; k < _dimY; k++) + acum += (*this)(i,k)* m(k,j); + res(i,j) = acum; + } + + return Matrix<T>(res); + + } + + Matrix<T> &operator*=(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimY?0:_dimX); + int y = (x!=0?0:m.dimY()); + T acum = nulo; + + Matrix<T> res(x,y); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < m.dimY(); j++) + { + acum = nulo; + for( int k = 0; k < _dimY; k++) + acum += (*this)(i,k)*m(k,j); + res(i,j) = acum; + } + + (*this) = res; + + return (*this); + + } + + Matrix<T> operator*(const T &elem) + { + Matrix<T> res(_dimX,_dimY); + + for(int i = 0; i < (_dimX*_dimY); i++) + res[i] = _matrix[i] * elem; + + return Matrix(res); + } + + Matrix<T> &operator*=(const T &elem) + { + for(int i = 0; i < (_dimX*_dimY); i++) + _matrix[i] *= elem; + + return (*this); + } + + Matrix<T> operator+(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimX?0:_dimX); + int y = (m.dimY()!=_dimY?0:_dimY); + + Matrix<T> res(x,y); + + for(int i = 0; i < (x*y); i++) + res[i] = _matrix[i] + m[i]; + + return Matrix<T>(res); + } + + Matrix<T> &operator+=(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimX?0:_dimX); + int y = (m.dimY()!=_dimY?0:_dimY); + + for(int i = 0; i < (x*y); i++) + _matrix[i] += m[i]; + + return (*this); + } + + Matrix<T> operator-(const Matrix<T> &m) + { + Matrix<T> res(); + + res = m * inverso; + return (*this) + res; + } + + + Matrix<T> &operator-=(const Matrix<T> &m) + { + Matrix<T> res(); + + res = m * inverso; + (*this) += res; + + return (*this); + } + + Matrix<T> Traspuesta() + { + Matrix<T> res(_dimY,_dimX); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < _dimY; j++) + res(j,i) = (*this)(i,j); + + return Matrix<T>(res); + } + + Matrix<T> &nula() + { + for(int i = 0; i < (_dimX*dimY); i++) + _matrix[i] = nulo; + + return (*this); + } + + Matrix<T> &identity() + { + register int k = 0; + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < _dimY; j++) + { + _matrix[k] = (i!=j?nulo:neutro); + k++; + } + + return (*this); + } + + unsigned int size() const + { + return (sizeof(T)*_dimX*_dimY); + } + + char *to_string() const + { + return (char *) _matrix; + } + + Matrix<T> &to_Matrix(char *_cadena) + { + T *ptr = (T *)_cadena; + + for(int i = 0; i < (_dimX*_dimY) ; i++) + { + _matrix[i] = *ptr; + ptr++; + } + + return (*this); + } + + + int dimX() const + { + return _dimX; + } + + int dimY() const + { + return _dimY; + } + + void remove() + { + if(_matrix != NULL) + delete [] _matrix; + } +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/Messages.h b/ProyectoFinal/AlgoritmoGenetico/malva/src/Messages.h new file mode 100644 index 0000000..e46b1d8 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/Messages.h @@ -0,0 +1,112 @@ +/*****************************************************************************/ +/*** ***/ +/*** Modificado por G.J.L.P. ***/ +/*** Añadidos nuevos mensajes que indican falta de algún ***/ +/*** Fichero de Configuración (No específico para ningún ***/ +/*** problema) o nuevos errores. ***/ +/*** ***/ +/*****************************************************************************/ + +#ifndef RLFAP_MESSAGES +#define RLFAP_MESSAGES + +#ifndef MAX_BUFFER +#define MAX_BUFFER 200 +#endif + +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +using namespace std; + +inline void show_message(int value) +{ + switch (value) + { + case 1: cout << endl << "Error: number of arguments in the execution call is incorrect !!" + << endl; break; + case 2: cout << endl << "Error: It's imposible find Configuration file !!" << endl; + break; + /* Específicos de RLFAP */ + case 3: cout << endl << "Error: It is imposible find the Celar problem definition file (cst.txt) !!" + << endl; break; + case 4: cout << endl << "Error: It is imposible find the Celar domains file (dom.txt) !!" + << endl; break; + case 5: cout << endl << "Error: It is imposible find the Celar links file (var.txt) !!" + << endl; break; + case 6: cout << endl << "Error: It is imposible find the Celar constraints file (ctr.txt) !!" + << endl; break; + /* Fallos de Memoria */ + case 7: cout << endl << "Error: No avalible memory for \"malloc\" operation !!" << endl; + break; + case 8: cout << endl << "Error: in \"free\" operation !!" << endl; + break; + /* Específicos del MaxCut */ + case 9: cout << endl << "Error: It is imposible find the Maxcut file (Maxcut.txt) !!" + << endl; break; + /* Genéricos de Falta de ficheros de configuracion adicionales al mensaje 2 */ + case 10: cout << endl << "Error: It's imposible find Configuration file (Config.cfg) !!" + << endl; break; + case 11: cout << endl << "Error: It's imposible find Skeleton Configuration File (Ske.cfg) !!" + << endl; break; + case 12: cout << endl << "Error: It's imposible find Instance Problem File !!" << endl; + break; + case 13: cout << endl << "Error: It's imposible find Resultate File !!" << endl; + break; + case 14: cout << endl << "Error: Index out of Range !!" << endl; + break; + default: cout << endl << "Unkown Error !!" << endl; + } + + cout << endl << " " << endl; + exit(-1); +} + +inline void continue_question() +{ + fflush(stdout); + cout << endl << "Press any key to continue..." << endl; + fflush(stdin); + getc(stdin); +} + +inline void get_path(const char *source,char *target) +{ + int last = 0; + + for(int i = 0; i < strlen(source); i++) + { + target[i] = source[i]; + if(target[i] == '/') + last = i; + } + target[last+1] = '\0'; +} + +inline unsigned count_lines(char *file_name) // returns the number of lines of a file +{ + char line[MAX_BUFFER]; + FILE *file; + int count=0; + + if ((file=fopen(file_name,"r"))==NULL) + { + fflush(stdout); + printf("File not found !"); + } + + while (!feof(file)) + { + if (fgets(line,MAX_BUFFER,file)) count++; + else + { + fclose(file); + break; + } + } + return count; +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/Rarray.h b/ProyectoFinal/AlgoritmoGenetico/malva/src/Rarray.h new file mode 100644 index 0000000..5d1a1c2 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/Rarray.h @@ -0,0 +1,145 @@ +/****************************************************************************** +*** *** +*** Template para el manejo dinámico de arrays *** +*** Añadido métodos para invertir todo o parte del array. *** +*** *** +******************************************************************************/ + +#ifndef ARRAY_INC +#define ARRAY_INC 1 +#include <iostream> +#include <assert.h> + +using namespace std; + +template<class E1> class Rarray +{ + private: + E1 *first; + int count; + + public: + Rarray() + { + first = NULL; + count = 0; + } + + ~Rarray() + { + remove(); + } + + E1* get_first() const + { + return first; + } + + void message_a(int cod) const + { + switch (cod) + { + case 1: cout << endl << "The size of array must be upper that 0 !!!" ; + } + } + + Rarray(const int size_a) + { + if (size_a<0) message_a(1); + first = new E1[size_a]; + count=size_a; + } + + void remove() + { + if (count!=0) + delete [] first; + } + + int size() const + { + return count; + } + + E1& operator[](int pos) const + { + return (E1&)(*(first + pos)); + } + + friend ostream& operator<< (ostream& os,const Rarray<E1>& a) + { + for (int i=0;i<a.size();i++) + os << endl << a[i]; + return os; + } + + Rarray<E1>& operator=(const Rarray<E1>& source) + { + remove(); + count = source.size(); + first = new E1[count]; + + for (int i=0;i<count;i++) + (*this)[i] = source[i]; + + return (*this); + } + + + Rarray<E1>& invert() + { + return invert(0,count-1); + } + + Rarray<E1>& invert(const int pos1, const int pos2) + { + int max,min,half,i,j; + E1 aux; + + if(pos1 > pos2) + { + max = pos1; + min = pos2; + } + else + { + max = pos2; + min = pos1; + } + + assert((min > 0) || (min < count-1)); + half = ((max-min)/2) + 1; + + for(i = min,j=max; i< half; i++,j--) + { + aux = first[min]; + first[min] = first[max]; + first[max] = aux; + } + + return (*this); + } + + Rarray<E1>& sort(int (*comp)(const E1 &,const E1 &)) + { + E1 aux; + int j; + + for (int i=1; i < count ; i++) + { + aux = first[i]; + j = i - 1; + while ( (comp(aux,first[j])) && (j >= 0) ) + { + first[j+1]= first[j]; + j--; + } + first[j+1] = aux; + } + + return (*this); + } + +}; // end of class + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/Rlist.h b/ProyectoFinal/AlgoritmoGenetico/malva/src/Rlist.h new file mode 100644 index 0000000..f561d0b --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/Rlist.h @@ -0,0 +1,415 @@ +/****************************************************************************** +*** *** +*** Este template sirve para el manejo de listas din�micas *** +*** *** +******************************************************************************/ + +#ifndef LIST_INC +#define LIST_INC 1 +#include <iostream> +#include <stdlib.h> +#include <Messages.h> + +using namespace std; + +template<class E> class Rlist_item +{ + public: + E *useful_data; // pointer to the structure stored in the list + Rlist_item<E> *next; + Rlist_item<E> *previous; + + Rlist_item(E& new_data) + { + useful_data=&new_data; + next=NULL; + previous=NULL; + } + + Rlist_item(E *new_data) + { + useful_data=new_data; + next=NULL; + previous=NULL; + } + + ~Rlist_item() + { + } + + Rlist_item<E>& next_item() + { + return *(next); + } + + Rlist_item<E>& previous_item() + { + return *(previous); + } + + bool is_last() + { + return (next==NULL); + } + + bool is_first() + { + return (previous==NULL); + } + + E& data() + { + return *(useful_data); + } +}; + +template<class E> class Rlist +{ + private: + Rlist_item<E> *first; // first item in the list + Rlist_item<E> *last; // last item un the list + int count; // number of items in the list + + public: + // constructor + Rlist() + { + first=NULL; + last=NULL; + count=0; + } + + // destructor + ~Rlist() + { + remove(); + } + + // Return the size of the list + int size() const + { return count; } + + // Go back to the initial state of the list + void reset() + { + first=NULL; + last=NULL; + count=0; + } + + // Add a item at the final of the list + Rlist<E>& append(E& new_item) + { + Rlist_item<E> *new_Rlist_item=new Rlist_item<E>(new_item); + if (first==NULL) + { + first=new_Rlist_item; + new_Rlist_item->next=NULL; + new_Rlist_item->previous=NULL; + } + else + { + last->next=new_Rlist_item; + new_Rlist_item->previous=last; + } + last=new_Rlist_item; + count++; + return *this; + } + + Rlist<E>& append(E *new_item) + { + append(*new_item); + return (*this); + } + + // Add a item in a position ( pos ) of the list + Rlist<E>& add_pos(E& new_item, const int pos) + { + if (pos==size()-1) + return append(new_item); + + if (pos==-1) + return add(new_item,NULL); + else + return add(new_item,get_at(pos).useful_data); + } + + // Add a item in the list in the position next to "previous item" + Rlist<E>& add(E& new_item,E *previous_item) + { + if (first==NULL) + return append(new_item); + + Rlist_item<E> *new_Rlist_item=new Rlist_item<E>(new_item); + + if (previous_item==NULL) // Add the item like the first of the list + { + new_Rlist_item->next=first; + new_Rlist_item->previous=NULL; + first->previous=new_Rlist_item; + first=new_Rlist_item; + } + else + { + int previous_position=get_position(*previous_item); + if (previous_position==-1) return(*this); + Rlist_item<E> *previous_Rlist_item = &( get_at(previous_position)); + new_Rlist_item->next=previous_Rlist_item->next; + new_Rlist_item->previous=previous_Rlist_item; + if (previous_Rlist_item->next!=NULL) + (previous_Rlist_item->next)->previous=new_Rlist_item; + else last=new_Rlist_item; + previous_Rlist_item->next=new_Rlist_item; + } + count++; + return *this; + } + + // Return a pointer to the first item of the list + Rlist_item<E> *get_first() const + { return first; } + + // Assign a item like the first item in the list + void set_first(Rlist_item<E> *new_first) + { first=new_first; } + + // Return a pointer to the last item of the list + Rlist_item<E> *get_last() const + { return last; } + + // Assign a item like the last item in the list + void set_last(Rlist_item<E> *new_last) + { last=new_last; } + + // Return the item at position "pos" + E& operator[](int pos) const + { + return *(get_at(pos).useful_data); + } + + // Return the Rlist_item at position "pos" + Rlist_item<E>& get_at(int pos) const + { + Rlist_item<E> *present=first; + for (int k=0;k<size();k++) + if (k==pos) return *present; + else present=present->next; + } + + // Return the item position in the list + int get_position(const E& item) const // probado + { + Rlist_item<E> *present=first; + int i=0; + + while(present!=NULL) + { + if (present->useful_data==&item) return i; + i++; + present=present->next; + } + return -1; // the object has not been found + } + + // Delete a item of the list + Rlist<E>& delete_item(E& item) + { + int position = get_position(item); + + if (position==-1) return *this; + Rlist_item<E> *present=&(get_at(position)); + + if (&item==first->useful_data) // is the first + { + if (&item==last->useful_data) + { + delete(first->useful_data); + delete(first); + first=NULL; + last=NULL; + count=0; + } + else + { + first=first->next; + first->previous=NULL; + delete(present->useful_data); + delete(present); + count--; + } + } + else + { + if (&item==last->useful_data) + { + last=present->previous; + last->next=NULL; + delete(present->useful_data); + delete(present); + count--; + } + else + { + (present->next)->previous=present->previous; + (present->previous)->next=present->next; + delete(present->useful_data); + delete(present); + count--; + } + } + return *this; + } + + // Delete a item of the list without free the useful_data + Rlist<E>& delete_item_1(E& item) + { + int position = get_position(item); + + if (position==-1) return *this; + Rlist_item<E> *present=&(get_at(position)); + + if (&item==first->useful_data) // is the first + { + if (&item==last->useful_data) + { + delete(first); + first=NULL; + last=NULL; + count=0; + } + else + { + first=first->next; + first->previous=NULL; + delete(present); + count--; + } + } + else + { + if (&item==last->useful_data) + { + last=present->previous; + last->next=NULL; + delete(present); + count--; + } + else + { + (present->next)->previous=present->previous; + (present->previous)->next=present->next; + delete(present); + count--; + } + } + return *this; + } + + // Delete item at position "pos" + Rlist<E>& delete_item_by_position(const int pos) + { return delete_item(*(get_at(pos).useful_data)); } + + // Delete the last item in the list + Rlist<E>& delete_last() + { return delete_item(*(last->useful_data)); } + + // delete all items in the list + Rlist<E>& remove() + { + Rlist_item<E> *next,*present=first; + while (present!=NULL) + { + next=present->next; + delete(present->useful_data); + delete(present); + present=next; + } + first=NULL; + last=NULL; + count=0; + return *this; + } + + // Join a new list to this list + Rlist<E>& join(Rlist<E>& new_list) + { + if (new_list.size()==0) + return *this; + + if (first==NULL) + { + first=new_list.get_first(); + last=new_list.get_last(); + } + else + { + last->next=new_list.get_first(); + (new_list.get_first())->previous=last; + last = new_list.get_last(); + } + count += new_list.size(); + new_list.reset(); + return *this; + } + + // Show items of the list + friend ostream& operator<<(ostream& os, const Rlist<E>& list) + { + Rlist_item<E> *present=list.get_first(); + if (list.get_first()==NULL) os << endl << "THE LIST IS EMPTY !!"; + while (present!=NULL) + { + os << endl << (*(present->useful_data)); + // Falta el operador para stat. + // (habra que ver) + present=present->next; + } + return os; + } + + // Copy the list passed + Rlist<E>& operator=(const Rlist<E>& source) + { + E *new_item; + remove(); + if (source.first==NULL && source.last==NULL) + { + first=NULL; + last=NULL; + count=0; + } + else + { + for (int i=0;i<source.size();i++) + { + if ((new_item=(E *)malloc(sizeof(E)))==NULL) + show_message(7); + (*new_item)=*(source.get_at(i).useful_data); + append(*new_item); + } + } + return *this; + } + + // Invert the order of items in the list + Rlist<E>& invert() + { + Rlist_item<E> *present,*interchange; + + present=first; + + for (int i=0;i<size();i++) + { + interchange=present->next; + present->next=present->previous; + present->previous=interchange; + present=interchange; + } + interchange=first; + first=last; + last=interchange; + return (*this); + } +}; // end of class +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/States.cc b/ProyectoFinal/AlgoritmoGenetico/malva/src/States.cc new file mode 100644 index 0000000..f36d197 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/States.cc @@ -0,0 +1,228 @@ +/****************************************************************************** + Modified by Carlos Cotta Porras + April 2001 + + Modified by G.J.L.P +******************************************************************************/ + + +#include <string.h> +#include "States.hh" + +// Methods of class State_Vble + + // constructors + State_Vble ::State_Vble () + { + name=NULL; + nitems=0; + length=0; + content=NULL; + } + + State_Vble ::State_Vble (const char *st_name) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + } + + State_Vble::State_Vble (const char *st_name,StateCenter& sc) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + sc.add(*this); + } + + State_Vble ::State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + set_contents(new_contents,new_nitems,new_length); + } + + State_Vble ::State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length,StateCenter& sc) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + set_contents(new_contents,new_nitems,new_length); + sc.add(*this); + } + + + // Set the name of a state vble. + void State_Vble ::set_name (const char* st_name) // Set the name of a state vble. + { + if (name!=NULL) + free(name); + name=strdup(st_name); + } + + // Get the name of a state vble. + char* State_Vble ::get_name () const // Get the name of a state vble. + { + return name; + } + + // Number of basic items + unsigned long State_Vble ::get_nitems() const // Number of basic items + { + return nitems; + } + + // Get the total number of bytes + unsigned long State_Vble ::get_length () const // Get the total number of bytes + { + return length; + } + + // Fill up a state vble. + void State_Vble ::set_contents (const char *new_contents, unsigned long new_nitems, unsigned long new_length) + { + if (content!=NULL) + free(content); + content=(char *)malloc(new_nitems * new_length); + memcpy(content,new_contents,(new_nitems*new_length)); + nitems=new_nitems; + length=new_length; + } + + // Obtain the contents of a state vble. + void *State_Vble ::get_contents (char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const + { + memcpy(read_contents,content,nitems * length); + read_nitems=nitems; + read_length=length; + return NULL; + } + + ostream& operator<< (ostream& os,const State_Vble& st) + { + os << endl << st.name + << endl << st.nitems + << endl << st.length + << endl << st.content; + + return os; + } + + State_Vble ::~State_Vble () + { + free(content); + free(name); + } + +// Methods of class StateCenter + + StateCenter::StateCenter():state_variables() + {} + + // searchs a state variable + State_Vble *StateCenter::find(const char *st_name) const + { + Rlist_item<State_Vble> *current_state=state_variables.get_first(); + + for (int i=0;i<state_variables.size();i++) + { + if (!(strcmp(current_state->data().get_name(),st_name))) + return &(current_state->data()); + current_state=¤t_state->next_item(); + } + return NULL; + } + + // Add one state variable + void StateCenter::add(State_Vble& st) + { + State_Vble *found_state=find(st.get_name()); + if (found_state==NULL) + state_variables.append(st); + else + cout << endl << "You are trying to introduce a state variable that is yet used in the skeleton !!" << st.get_name(); + } + + void StateCenter::add(State_Vble *st) + { + State_Vble *found_state=find(st->get_name()); + if (found_state==NULL) + state_variables.append(*st); + else + cout << endl << "You are trying to introduce a state variable that is yet used in the skeleton !!" << st->get_name(); + } + + // Remove one state variable + void StateCenter::remove(const char* st_name) + { + State_Vble *found_state=find(st_name); + if (found_state!=NULL) + state_variables.delete_item_1(*found_state); + } + + // Update the contents of one vble. + void StateCenter::update(const char* st_name, const State_Vble& st) const // Update the contents of one vble. + { + State_Vble *found_state=find(st_name); + if (found_state!=NULL) + { + char *a=(char *)malloc(found_state->get_nitems() * found_state->get_length()); + unsigned long nitems,length; + st.get_contents(a,nitems,length); + found_state->set_contents(a,nitems,length); + free(a); + } + } + + // Get a vble. with a given name + State_Vble& StateCenter::get(const char* st_name) const // Get a vble. with a given name + { + State_Vble *found_state=find(st_name); + return *found_state; + } + + // Allows an easy iterated extraction + State_Vble* StateCenter::get_next(const State_Vble& st) const + { + State_Vble *found_state=find(st.get_name()); + if (found_state==NULL) return NULL; + if ( state_variables.get_at(state_variables.get_position(*found_state)).is_last()) return NULL; + else return &(state_variables.get_at(state_variables.get_position(*found_state)).next_item().data()); + } + + // returns the number of state variables + unsigned int StateCenter::size() const + { + return state_variables.size(); + } + + // Obtain the contents of a state vble. of name st_name + void StateCenter::get_contents_state_variable(const char *st_name,char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const + { + get(st_name).get_contents(read_contents,read_nitems,read_length); + } + + // Fill up a state vble.of name st_name + void StateCenter::set_contents_state_variable(const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) const + { + get(st_name).set_contents(new_contents,new_nitems,new_length); + } + + void StateCenter::removeAll() + { + while(state_variables.get_first()) + { + Rlist_item<State_Vble>* v = state_variables.get_first(); + remove(v->useful_data->get_name()); + } + } + + StateCenter::~StateCenter() + { + removeAll(); + } diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/States.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/States.hh new file mode 100644 index 0000000..e3a215f --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/States.hh @@ -0,0 +1,64 @@ +/******************************************************************************************************** +*** *** +*** Class StateCenter: Pool of state variables for skeletons *** +*** *** +*** Class State_Vble: State Variable of a skeleton *** +*** *** +*********************************************************************************************************/ + +#ifndef STATE_CENTER +#define STATE_CENTER 1 + +#include "Rlist.h" +#include <iostream> + +class StateCenter; + +class State_Vble +{ + private: + char *name; + unsigned long nitems; + unsigned long length; + char *content; + + public: + // constructors + State_Vble (); + State_Vble (const char *st_name); + State_Vble (const char *st_name,StateCenter& sc); + State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length); + State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length,StateCenter& sc); + + void set_name (const char* st_name); // Set the name of a state vble. + char* get_name () const; // Get the name of a state vble. + unsigned long get_nitems() const; + unsigned long get_length () const; // Get the total number of bytes + void set_contents (const char *new_contents, unsigned long new_nitems, unsigned long new_length); // Fill up a state vble. + void *get_contents (char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const; // Obtain the contents of a state vble. + friend ostream& operator<< (ostream& os,const State_Vble& st); + ~State_Vble (); +}; + +class StateCenter +{ + private: + Rlist<State_Vble> state_variables; + + public: + StateCenter(); + State_Vble *find(const char *st_name) const; // search a state variable + void add(State_Vble& st); // Add one state variable + void add(State_Vble *st); // Add one state variable + void remove(const char* st_name); // Remove one state variable + void removeAll(); // Removes all variables + void update(const char* st_name, const State_Vble& st) const; // Update the contents of one vble. + State_Vble& get(const char* st_name) const; // Get a vble. with a given name + State_Vble* get_next(const State_Vble& st) const; // Allows an easy iterated extraction + unsigned int size() const; // returns the number of state variables + void get_contents_state_variable(const char *st_name,char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const; // Obtain the contents of a state vble. of name st_name + void set_contents_state_variable(const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) const; // Fill up a state vble.of name st_name + ~StateCenter(); +}; + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/States.o b/ProyectoFinal/AlgoritmoGenetico/malva/src/States.o new file mode 100644 index 0000000000000000000000000000000000000000..f5e95c8928fb22e26363c12820d0e56fd98709d2 GIT binary patch literal 12968 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/mallba.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/mallba.hh new file mode 100644 index 0000000..e4a35c0 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/mallba.hh @@ -0,0 +1,26 @@ +/***************************************************************************** +*** *** +*** Este fichero hace algunas declaraciones y declara algunos tipos comu- *** +*** nes a todos los algoritmos implementados. *** +*** *** +*****************************************************************************/ + +#ifndef INC_mallba_hh +#define INC_mallba_hh + +#define skeleton namespace +#define requires +#define provides +#define hybridizes(x) +#define inherits typedef +#define as + +enum Direction { minimize=-1,maximize=1}; + +extern const double plus_infinity; +extern const double minus_infinity; + +#define false 0 +#define true 1 + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.cc b/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.cc new file mode 100644 index 0000000..932e89e --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.cc @@ -0,0 +1,380 @@ +/*************************************************************************** + *** netstream.cc *** + *** v1.6 - July 2001 *** + ** *** + *** v1.5 - March 2001 *** + *** v1.0 - November 2000 *** + *** *** + *** v1.5 extends v1.0: *** + *** .- Changes metods init() and finalize() to be static *** + *** .- Incorporates process group management *** + *** .- Do not consider LEDA anymore *** + *** .- Contains a method "int my_pid()" for easy invokations *** + *** .- Adds "unsigned" and "long double" input/output *** + *** *** + *** v1.6 extends v1.5: *** + ** .- Internal in/out buffers for packed separated *** + *** *** + *** Communication services for LAN/WAN use following the message *** + *** passing paradigm. *** + *** STREAM C++ VERSION *** + *** MPI implementation *** + *** Developed by Erique Alba *** + ***************************************************************************/ +#include "netstream.hh" +// Default constructor +NetStream::NetStream() +{ + this->reset(); // Reset to default values member variables + packin_buffer = new char[MAX_PACK_BUFFER_SIZE]; + packout_buffer = new char[MAX_PACK_BUFFER_SIZE]; +} +// Init the underlying communication library (MPI) +NetStream::NetStream (int argc, char ** argv) +{ + init(argc,argv); + this->reset(); + packin_buffer = new char[MAX_PACK_BUFFER_SIZE]; + packout_buffer = new char[MAX_PACK_BUFFER_SIZE]; +} +// Default destructor +NetStream::~NetStream() +{ + delete [] packin_buffer; delete [] packout_buffer; + this->reset(); +} +// Give default values to member variables +void NetStream::reset(void) +{ + default_target = default_source = 0; + pack_in_progress = false; + packin_index = packout_index = 0; + pending_input_packet = false; + pack_in = pack_out = false; + broadcast = false; + my_communicator = MPI_COMM_WORLD; +} +// Init the communication system. Invoke it only ONCE +void NetStream::init(int argc, char** argv) +{ + static bool system_up = false; // Is MPI already running? + if (!system_up) + { MPI_Init(&argc,&argv); + system_up = true; + } +} +// Shutdown the communication system. Invoke it ONCE +void NetStream::finalize(void) +{ + MPI_Finalize(); // Unconditional Finalization +} +// BASIC INPUT/OUTPUT SERVICES +// =================================================================================== + +NetStream& NetStream::operator>> (bool& d) +{ rcv(&d,1,NET_BOOL,default_source); return(*this); } + +NetStream& NetStream::operator<< (bool d) +{ send(&d,1,NET_BOOL,default_target); return(*this); } +NetStream& NetStream::operator>> (char& d) +{ rcv(&d,1,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (char d) +{ send(&d,1,NET_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (short& d) +{ rcv(&d,1,NET_SHORT,default_source); return(*this); } +NetStream& NetStream::operator<< (short d) +{ send(&d,1,NET_SHORT,default_target); return(*this); } +NetStream& NetStream::operator>> (int& d) +{ rcv(&d,1,NET_INT,default_source); return(*this); } +NetStream& NetStream::operator<< (int d) +{ send(&d,1,NET_INT,default_target); return(*this); } +NetStream& NetStream::operator>> (long& d) +{ rcv(&d,1,NET_LONG,default_source); return(*this); } +NetStream& NetStream::operator<< (long d) +{ send(&d,1,NET_LONG,default_target); return(*this); } +NetStream& NetStream::operator>> (float& d) +{ rcv(&d,1,NET_FLOAT,default_source); return(*this); } +NetStream& NetStream::operator<< (float d) +{ send(&d,1,NET_FLOAT,default_target); return(*this); } +NetStream& NetStream::operator>> (double& d) +{ rcv(&d,1,NET_DOUBLE,default_source); return(*this); } +NetStream& NetStream::operator<< (double d) +{ send(&d,1,NET_DOUBLE,default_target); return(*this); } +NetStream& NetStream::operator>> (char* d) +{ rcv(d,MAX_MSG_LENGTH,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (char* d) +{ send(d,strlen(d)+1,NET_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (void* d) +{ rcv(d,MAX_MSG_LENGTH,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (void* d) +{ send(d,strlen((char*)d)+1,NET_CHAR,default_target); return(*this); } +// Extended data types from version 1.5 on +NetStream& NetStream::operator>> (unsigned char& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_CHAR,default_source);return(*this); } + +NetStream& NetStream::operator<< (unsigned char d) +{ send(&d,1,NET_UNSIGNED_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned short int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_SHORT,default_source);return(*this); } +NetStream& NetStream::operator<< (unsigned short int d) +{ send(&d,1,NET_UNSIGNED_SHORT,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED,default_source); return(*this); } + +NetStream& NetStream::operator<< (unsigned int d) +{ send(&d,1,NET_UNSIGNED,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned long int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_LONG,default_source);return(*this); } + +NetStream& NetStream::operator<< (unsigned long int d) +{ send(&d,1,NET_UNSIGNED_LONG,default_target); return(*this); } +NetStream& NetStream::operator>> (long double& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_LONG_DOUBLE,default_source); return(*this); } + +NetStream& NetStream::operator<< (long double d) +{ send(&d,1,NET_LONG_DOUBLE,default_target); return(*this); } +// SET-GET TARGET AND SOURCE PROCESSES +NetStream& __set_target(NetStream& n, const int p) { return n._set_target(p); } +NetStream& NetStream::_set_target(const int p) +{ assert(p>=0); default_target = p; return (*this); } +NetStream& __get_target(NetStream& n, int* p) { return n._get_target(p); } +NetStream& NetStream::_get_target(int* p) +{ *p = default_target; return (*this); } +NetStream& __set_source(NetStream& n, const int p) { return n._set_source(p); } +NetStream& NetStream::_set_source(const int p) +{ /*assert(p>=0);*/ default_source = p; return (*this); } +NetStream& __get_source(NetStream& n, int* p) { return n._get_source(p); } +NetStream& NetStream::_get_source(int* p) +{ *p = default_source; return (*this); } +// Get the number of processes involved in the communications +int NetStream::pnumber(void) +{ int numprocs, rvalue; + rvalue = MPI_Comm_size(my_communicator,&numprocs); + assert(rvalue==MPI_SUCCESS); + return numprocs; +} +// MANIPULATORS: SYNCHRONIZATION AND PACKING SERVICES +// =================================================================================== +// Get the process ID [0, 1, 2, ...] fro the calling process +NetStream& __my_pid(NetStream& n, int* pid) +{ + return n._my_pid(pid); +} +NetStream& NetStream::_my_pid(int* pid) +{ + MPI_Comm_rank(my_communicator,pid); + return (*this); +} +// EASY access to rank - Returns the process ID of the calling process +int NetStream::my_pid(void) +{ int pid; + this->_my_pid(&pid); + return pid; +} +// Sit and wait until all processes are in the same barrier +// Can be used as a MANIPULATOR +NetStream& barrier(NetStream& n) +{ + return n._barrier(); +} +NetStream& NetStream::_barrier(void) +{ int status; + status = MPI_Barrier(my_communicator); + assert(status==MPI_SUCCESS); + return (*this); +} +// Wait for an incoming message in any input stream +NetStream& NetStream::_wait(const int stream_type) // class +{ + int rvalue; + MPI_Status status; + assert(stream_type==regular||stream_type==packed||stream_type==any); + if( ((stream_type==packed) || (stream_type==any) )&& (pending_input_packet) ) + //if( (stream_type==packed) && (pending_input_packet) ) + return (*this); // wait befor packet_begin when already received + rvalue = MPI_Probe(default_source,stream_type,my_communicator,&status); + assert(rvalue==MPI_SUCCESS); + return (*this); +} + +NetStream& NetStream::_wait2(const int stream_type, int& tipo) // class +{ + int rvalue; + MPI_Status status; + assert(stream_type==regular||stream_type==packed||stream_type==any); + if( ((stream_type==packed) || (stream_type==any) )&& (pending_input_packet) ) + //if( (stream_type==packed) && (pending_input_packet) ) + return (*this); // wait befor packet_begin when already received + rvalue = MPI_Probe(default_source,stream_type,my_communicator,&status); + assert(rvalue==MPI_SUCCESS); + if (status.MPI_SOURCE == 0){ + tipo = 1; + } + return (*this); +} +NetStream& __wait(NetStream& n, const int stream_type) // helper +{ + return n._wait(stream_type); +} +// Marks the beginning of a packed information +NetStream& pack_begin(NetStream& n) +{ + return n._pack_begin(); +} +NetStream& NetStream::_pack_begin(void) +{ + int rvalue=MPI_SUCCESS; + MPI_Status status; + if(!pack_in_progress) + { pack_in_progress = true; + packin_index = packout_index = 0; + pack_in = false; + pack_out = false; + if (!pending_input_packet) + { _probe(packed,pending_input_packet); + if(pending_input_packet) + rvalue = MPI_Recv(packin_buffer, MAX_PACK_BUFFER_SIZE, NET_PACKED, + default_source, PACKED_STREAM_TAG, my_communicator, &status); + } + } + return (*this); +} +// Marks the end of a packed and flush it to the net +NetStream& pack_end(NetStream& n) +{ + return n._pack_end(); +} +NetStream& NetStream::_pack_end(void) +{ + int rvalue, mypid; + if (pack_in_progress) + { + if(pack_out) + { if(broadcast) // Packet broadcast + { broadcast = false; + _my_pid(&mypid); + rvalue = MPI_Bcast(packout_buffer,packout_index,NET_PACKED, + mypid,my_communicator); + assert(rvalue==MPI_SUCCESS); + } + else + { rvalue = MPI_Send(packout_buffer, packout_index, NET_PACKED, + default_target,PACKED_STREAM_TAG,my_communicator); + assert(rvalue==MPI_SUCCESS); + } + } + pack_in_progress = false; + pack_in = pack_out = false; + packin_index = packout_index = 0 ; + } + return (*this); +} +// Check whether there are awaiting data +NetStream& probe(NetStream& n, const int stream_type, int& pending) +{ + return n._probe(stream_type, pending); +} +NetStream& NetStream::_probe(const int stream_type, int& pending) +{ + MPI_Status status; + int rvalue; + assert(stream_type==regular||stream_type==packed||stream_type==any); + rvalue = MPI_Iprobe(default_source,stream_type,my_communicator,&pending,&status); + assert(rvalue==MPI_SUCCESS); + return (*this); +} +// Broadcast a message to all the processes +NetStream& broadcast(NetStream& n) +{ + return n._broadcast(); +} +NetStream& NetStream::_broadcast(void) +{ + broadcast = true; + return (*this); +} +// PRIVATE SERVICES +// =================================================================================== +// Usually, the length is the number of bytes for every net type +// When packing we must use in the pack calls the numer of items (length divided by type size) +// Any char is encoded with a leading field of length +void NetStream::send(void* d, const int len, const NET_TYPE type, const int target) +{ + int rvalue = MPI_SUCCESS, length = len; + // PACKING SERVICE + if(pack_in_progress) + { + pack_out = true; + assert(pack_out!=pack_in); // Error condition + if(type==NET_CHAR) + send(&length,sizeof(NET_INT),NET_INT,target); // Recursive call to store string length + else + length = 1; + rvalue = MPI_Pack(d,length,type,packout_buffer,MAX_PACK_BUFFER_SIZE,&packout_index,my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + if(broadcast) // Regular broadcast, packed broadcast managed in _pack_end() + { int mypid; + + broadcast = false; + _my_pid(&mypid); + rvalue = MPI_Bcast(d,len,type,mypid,my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + rvalue = MPI_Send(d,len,type,target,REGULAR_STREAM_TAG,my_communicator); + assert(rvalue==MPI_SUCCESS); +} +void NetStream::rcv (void* d, const int len, const NET_TYPE type, const int source) +{ MPI_Status status; + int rvalue = MPI_SUCCESS, length=len; + if(pack_in_progress) + { +// if(!pack_in && !pending_input_packet) +// rvalue = MPI_Recv(packin_buffer, MAX_PACK_BUFFER_SIZE, NET_PACKED, +// default_source, PACKED_STREAM_TAG, my_communicator, &status); + pack_in = true; + pending_input_packet = false; + assert(pack_out!=pack_in); + if(type==NET_CHAR) + rcv(&length,sizeof(NET_INT),NET_INT,source); // Gets the string length + else + length = 1; + rvalue = MPI_Unpack(packin_buffer, MAX_PACK_BUFFER_SIZE, &packin_index, d, + length, type, my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + + rvalue=MPI_Recv(d,len,type,source,REGULAR_STREAM_TAG,my_communicator,&status); + assert(status.MPI_ERROR==MPI_SUCCESS); + assert(rvalue==MPI_SUCCESS); +} +/////////////////////////////////////// GROUP MANAGEMENT //////////////////////////////// +// Set the netstream to a new communicator +void NetStream::set_communicator(NET_Comm comm) +{ + my_communicator = comm; +} +// Get the present communicator in this netstream +NET_Comm NetStream::get_communicator(void) +{ + return my_communicator; +} +// Create a new group inside the present communicator +NET_Comm NetStream::create_group(NET_Comm comm, int color, int key) +{ int rvalue; + NET_Comm newcomm; + rvalue=MPI_Comm_split(comm,color,key,&newcomm); + assert(rvalue==MPI_SUCCESS); + return newcomm; +} +// Create a bridge between local and remote MATCHING call +NET_Comm NetStream::create_inter_group(NET_Comm lcomm, int lrank, NET_Comm bcomm, int rrank, int strtype) +{ int rvalue; + NET_Comm newcomm; + rvalue=MPI_Intercomm_create(lcomm,lrank,bcomm,rrank,strtype,&newcomm); + assert(rvalue==MPI_SUCCESS); + return newcomm; +} diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.hh new file mode 100644 index 0000000..5c24a3d --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.hh @@ -0,0 +1,161 @@ +/*************************************************************************** + *** netstream.cc *** + *** v1.6 - July 2001 *** + ** *** + *** v1.5 - March 2001 *** + *** v1.0 - November 2000 *** + *** *** + *** v1.5 extends v1.0: *** + *** .- Changes metods init() and finalize() to be static *** + *** .- Incorporates process group management *** + *** .- Do not consider LEDA anymore *** + *** .- Contains a method "int my_pid()" for easy invokations *** + *** .- Adds "unsigned" and "long double" input/output *** + *** *** + *** v1.6 extends v1.5: *** + ** .- Internal in/out buffers for packed separated *** + *** *** + *** Communication services for LAN/WAN use following the message *** + *** passing paradigm. *** + *** STREAM C++ VERSION *** + *** MPI implementation *** + *** Developed by Erique Alba *** + ***************************************************************************/ +#ifndef INC_netstream +#define INC_netstream +#include "mpi.h" +#include <assert.h> +#include <string.h> +// Class NetStream allows to define and use network streams trhough LAN and WAN +#define REGULAR_STREAM_TAG 0 // Used for tagging MPI regular messages +#define PACKED_STREAM_TAG 1 // Used for tagging MPI packet messages +#define NET_TYPE MPI_Datatype // Network allowable data types +#define NET_BOOL MPI_CHAR // Bools like chars +#define NET_CHAR MPI_CHAR +#define NET_SHORT MPI_SHORT +#define NET_INT MPI_INT +#define NET_LONG MPI_LONG +#define NET_UNSIGNED_CHAR MPI_UNSIGNED_CHAR +#define NET_UNSIGNED_SHORT MPI_UNSIGNED_SHORT +#define NET_UNSIGNED MPI_UNSIGNED +#define NET_UNSIGNED_LONG MPI_UNSIGNED_LONG +#define NET_FLOAT MPI_FLOAT +#define NET_DOUBLE MPI_DOUBLE +#define NET_LONG_DOUBLE MPI_LONG_DOUBLE +#define NET_BYTE MPI_BYTE +#define NET_PACKED MPI_PACKED +#define NET_Comm MPI_Comm +#define MAX_MSG_LENGTH 204800 // Max length of a message +#define MAX_PACK_BUFFER_SIZE 204800 // Max length of a packed message +// Help structure for manipulators having one int& argument +class NetStream; +struct smanip1c // "const int" +{ NetStream& (*f)(NetStream&, const int); // The ONE argument function + int i; // The argument + smanip1c( NetStream&(*ff)(NetStream&,const int), int ii) : f(ff), i(ii) {} // Constuctor +}; +struct smanip1 // "int*" note: references do not work! "int&" +{ NetStream& (*f)(NetStream&, int*); // The ONE argument function + int* i; // The argument + smanip1( NetStream&(*ff)(NetStream&, int*), int* ii) : f(ff), i(ii) {} // Constuctor +}; +// Tags for the available streams +const int any = MPI_ANY_TAG; // Tag value valid for any stream +const int regular = REGULAR_STREAM_TAG; // Tag value for regular stream of data +const int packed = PACKED_STREAM_TAG; // Tag value for packed stream of data +// Tags for sources +const int any_source = MPI_ANY_SOURCE; // Tag value valid for any source +class NetStream +{ + public: + NetStream (); // Default constructor + // Constructor with source integer left unchanged + NetStream (int, char **); // Init the communications + ~NetStream (); // Default destructor + static void init(int,char**); // Init the communication system. Invoke it only ONCE + static void finalize(void); // Shutdown the communication system. Invoke it ONCE + // GROUP management + void set_communicator(NET_Comm comm); // Set the netstream to a new communicator + NET_Comm get_communicator(void); // Get the present communicator in this netstream + static NET_Comm create_group(NET_Comm comm, int color, int key); // Create a new group inside the present communicator + // Create a bridge between local and remote MATCHING call + static NET_Comm create_inter_group(NET_Comm lcomm, int lrank, NET_Comm bcomm, int rrank, int strtrype); + +// BASIC INPUT SERVICES <comments> BASIC OUTPUT SERVICES +// ============================================================================================================ + NetStream& operator>> (bool& d); NetStream& operator<< (bool d); + NetStream& operator>> (char& d); NetStream& operator<< (char d); + NetStream& operator>> (short& d); NetStream& operator<< (short d); + NetStream& operator>> (int& d); NetStream& operator<< (int d); + NetStream& operator>> (long& d); NetStream& operator<< (long d); + NetStream& operator>> (float& d); NetStream& operator<< (float d); + NetStream& operator>> (double& d); NetStream& operator<< (double d); + NetStream& operator>> (char* d); /*NULL terminated*/ NetStream& operator<< (char* d); + NetStream& operator>> (void* d); /*NULL terminated*/ NetStream& operator<< (void* d); + // Extended data types from version 1.5 on + NetStream& operator>> (unsigned char& d); NetStream& operator<< (unsigned char d); + NetStream& operator>> (unsigned short int& d); NetStream& operator<< (unsigned short int d); + NetStream& operator>> (unsigned int& d); NetStream& operator<< (unsigned int d); + NetStream& operator>> (unsigned long int& d); NetStream& operator<< (unsigned long int d); + NetStream& operator>> (long double& d); NetStream& operator<< (long double d); + int pnumber(void); // Returns the number of processes + bool broadcast; // Determines whether the next sent message is for broadcasting + // Input MANIPULATORS for modifying the behavior of the channel on the fly + // NO ARGUMENTS + NetStream& operator<< (NetStream& (*f)(NetStream& n)) { return f(*this); } // NO arguments + NetStream& _barrier(void); // Sit and wait until all processes are in barrier + NetStream& _pack_begin(void); // Marks the beginning of a packed information + NetStream& _pack_end(void); // Marks the end of a packed and flush it to the net + NetStream& _probe(const int stream_type, int& pending); // Check whether there are awaiting data + NetStream& _broadcast(void); // Broadcast a message to all the processes + // ONE ARGUMENT + // "const int" + NetStream& operator<< (smanip1c m) { return m.f((*this),m.i); }// ONE int& argument constant + // "int*" + NetStream& operator<< (smanip1 m) { return m.f((*this),m.i); }// ONE int& argument + // BASIC CLASS METHODS FOR MANIPULATORS + NetStream& _my_pid(int* pid); // Returns the process ID of the calling process + NetStream& _wait(const int stream_type); // Wait for an incoming message in the specified stream + NetStream& _wait2(const int stream_type, int& tipo); + NetStream& _set_target(const int p); // Stablish "p" as the default receiver + NetStream& _get_target(int* p); // Get into "p" the default receiver + NetStream& _set_source(const int p); // Stablish "p" as the default transmitter + NetStream& _get_source(int* p); // Get into "p" the default transmitter + // AUXILIAR PUBLIC METHODS FOR ALLOWING EASY MANAGEMENTS OF NETSTREAMS + int my_pid(void); // Returns the process ID of the calling process + private: + int default_target, default_source; // Default process IDs to send-recv data to-from + bool pack_in_progress; // Defines whether a packet is being defined with "pack_begin-pack_end" + int packin_index; // Index to be used for extracting from a IN packed message - v1.6 + int packout_index; // Index to be used for adding to an OUT packed message - v1.6 + int pending_input_packet;//Is there a pending packet already read into the IN buffer? - v1.6 + char* packin_buffer; // Buffer to temporary storage of the IN packed being defined - v1.6 + char* packout_buffer; // Buffer to temporary storage of the OUT packed being defined - v1.6 + bool pack_in, pack_out; // Define whether input-output packed message is being used + void reset(void); // Reset member variables of this class + NET_Comm my_communicator; // Communicator of this netstream + void send(void* d, const int len, const NET_TYPE type, const int target); + void rcv (void* d, const int len, const NET_TYPE type, const int source); +}; // class NetStream + // MANIPULATORS (must be static or non-member methods in C++ -mpiCC only allows non-member!-) + // NO ARGUMENTS + NetStream& barrier(NetStream& n); // Sit and wait until all processes are in barrier + NetStream& broadcast(NetStream& n); // Broadcast a message to all the processes + NetStream& pack_begin(NetStream& n); // Marks the beginning of a packed information + NetStream& pack_end(NetStream& n); // Marks the end of a packed and flush it to the net + // ONE ARGUMENT + NetStream& __my_pid(NetStream& n, int* pid); // Returns the process ID of the calling process + inline smanip1 my_pid(int* pid){ return smanip1(__my_pid,pid); } // manipulator + NetStream& __wait(NetStream& n, const int stream_type);// Wait for an incoming message - helper + inline smanip1c wait(const int stream_type){ return smanip1c(__wait,stream_type); } // manipulator + NetStream& __set_target(NetStream& n, const int p); // Stablish "p" as the default receiver + inline smanip1c set_target(const int p){ return smanip1c(__set_target,p); } // manipulator + NetStream& __get_target(NetStream& n, int* p); // Get into "p" the default receiver + inline smanip1 get_target(int* p){ return smanip1(__get_target,p); } // manipulator + NetStream& __set_source(NetStream& n, const int p); // Stablish "p" as the default transmitter + inline smanip1c set_source(const int p){ return smanip1c(__set_source,p); } // manipulator + NetStream& __get_source(NetStream& n, int* p); // Get into "p" the default transmitter + inline smanip1 get_source(int* p){ return smanip1(__get_source,p); } // manipulator + // TWO ARGUMENTS - not used yet + NetStream& probe(NetStream& n, const int stream_type, int& pending); // Check whether there are awaiting data +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.o b/ProyectoFinal/AlgoritmoGenetico/malva/src/netstream.o new file mode 100644 index 0000000000000000000000000000000000000000..fb40ece360fb739d83d40beffbf1b01c031a15aa GIT binary patch literal 18752 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 WPq&ZTAtmkCLk1+?U$LKx<M;m{=Bs=F literal 0 HcmV?d00001 diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/random.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/random.hh new file mode 100644 index 0000000..ae6bde6 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/random.hh @@ -0,0 +1,50 @@ +/****************************************************************************** +*** *** +*** Este fichero contiene funciones (en general inlines) para generar núme- *** +*** ros aleatorios y otras funciones relacionadas con ello *** +*** *** +*******************************************************************************/ + +#ifndef INC_random_hh +#define INC_random_hh + +#include <stdlib.h> + + +inline double undefined () +{ + double zero = 0; + return zero/zero; +} + +// Returns a valeu greater than any other +inline double infinity () +{ + double one=1.0; + double zero=0.0; + return one/zero; +} + +// Returns a random number in [0,1]. +inline double rand01 () +{ + return drand48(); +} + +// Returns a random number +inline int rand_int (float min,float max) +{ + int value=rand(); + int range= (int)(max - min); + int order = value % (range+1); + return ((int)min + order); +} + +// selects a seed +inline void random_seed(long int seed) +{ + srand48(seed); + srand(seed); +} + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/src/time.hh b/ProyectoFinal/AlgoritmoGenetico/malva/src/time.hh new file mode 100644 index 0000000..088f4d5 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/src/time.hh @@ -0,0 +1,43 @@ +/****************************************************************************** +*** *** +*** Este fichero incluye algunas funciones útiles para la medicion de tiem- *** +*** pos. *** +*** *** +******************************************************************************/ + +#ifndef INC_time_hh +#define INC_time_hh + +#define MAXTIME 4294 + +#include <time.h> +#include <sys/time.h> +#include <unistd.h> + +// return time in microseconds +inline float _used_time() +{ + struct timeval tv ; + static long tiempo = -1; + float u_clock; + + gettimeofday(&tv,NULL); + + if(tiempo < 0) tiempo = tv.tv_sec; + + u_clock = ((float)(tv.tv_sec - tiempo)*1000000.0) + ((float)tv.tv_usec); + return u_clock; + +} + + +inline float _used_time(float time) +{ + float dif=_used_time() - time; + if (dif<0) dif = 0; + return dif; +} + + + +#endif diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_aco b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_aco new file mode 100644 index 0000000..8426ce4 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_aco @@ -0,0 +1,12 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pop b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pop new file mode 100644 index 0000000..8512575 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pop @@ -0,0 +1,13 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.eval +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pso b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pso new file mode 100644 index 0000000..672f857 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_pso @@ -0,0 +1,12 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $4}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_sa b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_sa new file mode 100644 index 0000000..d006462 --- /dev/null +++ b/ProyectoFinal/AlgoritmoGenetico/malva/stat/file_stat_sa @@ -0,0 +1,13 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.eval +head -n $head_op $1 | tail -n $tail_op | gawk '{print $4}' > $1.init_temp +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.best_temp +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/AlgoritmoGenetico/malva/uml-comun.gif b/ProyectoFinal/AlgoritmoGenetico/malva/uml-comun.gif new file mode 100644 index 0000000000000000000000000000000000000000..e86a0eb3c9795f45438a28d1e81e8e0b6ec2b90b GIT binary patch literal 13660 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/.Rhistory b/ProyectoFinal/CHC/malva/.Rhistory new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/CHC/malva/.cproject b/ProyectoFinal/CHC/malva/.cproject new file mode 100644 index 0000000..4d31d90 --- /dev/null +++ b/ProyectoFinal/CHC/malva/.cproject @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?fileVersion 4.0.0?> + +<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> + <storageModule moduleId="org.eclipse.cdt.core.settings"> + <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1028103499"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1028103499" moduleId="org.eclipse.cdt.core.settings" name="Default"> + <externalSettings/> + <extensions> + <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> + <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + </extensions> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1028103499" name="Default" parent="org.eclipse.cdt.build.core.emptycfg"> + <folderInfo id="cdt.managedbuild.toolchain.gnu.base.1028103499.1127827476" name="/" resourcePath=""> + <toolChain id="cdt.managedbuild.toolchain.gnu.base.765753298" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base"> + <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1817766457" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/> + <builder id="cdt.managedbuild.target.gnu.builder.base.1493464269" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/> + <tool id="cdt.managedbuild.tool.gnu.archiver.base.1457471918" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> + <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1006777203" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"> + <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.224865571" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> + </tool> + <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.2140176745" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"> + <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.587099952" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> + </tool> + <tool id="cdt.managedbuild.tool.gnu.c.linker.base.1988570852" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/> + <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1956065400" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"> + <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.507618374" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> + <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> + <additionalInput kind="additionalinput" paths="$(LIBS)"/> + </inputType> + </tool> + <tool id="cdt.managedbuild.tool.gnu.assembler.base.535458070" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"> + <inputType id="cdt.managedbuild.tool.gnu.assembler.input.584095528" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> + </tool> + </toolChain> + </folderInfo> + </configuration> + </storageModule> + <storageModule moduleId="scannerConfiguration"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> + <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="makefileGenerator"> + <runAction arguments="-E -P -v -dD" command="" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC"> + <buildOutputProvider> + <openAction enabled="true" filePath=""/> + <parser enabled="true"/> + </buildOutputProvider> + <scannerInfoProvider id="specsFile"> + <runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/> + <parser enabled="true"/> + </scannerInfoProvider> + </profile> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <project id="malva.null.2024921052" name="malva"/> + </storageModule> +</cproject> diff --git a/ProyectoFinal/CHC/malva/.gitignore b/ProyectoFinal/CHC/malva/.gitignore new file mode 100644 index 0000000..42fcba1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/.gitignore @@ -0,0 +1,6 @@ +.cproject/ +.project/ +.svn/ +.idea/ +.DS_Store + diff --git a/ProyectoFinal/CHC/malva/.project b/ProyectoFinal/CHC/malva/.project new file mode 100644 index 0000000..1bb914c --- /dev/null +++ b/ProyectoFinal/CHC/malva/.project @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>Malva</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> + <triggers>clean,full,incremental,</triggers> + <arguments> + <dictionary> + <key>?name?</key> + <value></value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.append_environment</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.autoBuildTarget</key> + <value>all</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.buildArguments</key> + <value></value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.buildCommand</key> + <value>make</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.cleanBuildTarget</key> + <value>clean</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.contents</key> + <value>org.eclipse.cdt.make.core.activeConfigSettings</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableAutoBuild</key> + <value>false</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableCleanBuild</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.enableFullBuild</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.fullBuildTarget</key> + <value>all</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.stopOnError</key> + <value>true</value> + </dictionary> + <dictionary> + <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key> + <value>true</value> + </dictionary> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.cdt.core.cnature</nature> + <nature>org.eclipse.cdt.core.ccnature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> + </natures> +</projectDescription> diff --git a/ProyectoFinal/CHC/malva/Makefile b/ProyectoFinal/CHC/malva/Makefile new file mode 100644 index 0000000..a662e76 --- /dev/null +++ b/ProyectoFinal/CHC/malva/Makefile @@ -0,0 +1,24 @@ +default: + @echo "Make what? (all, libs, skeletons, clean)" + +all: + (cd inc ; rm -f Mallba) + (cd inc ; ./inc.env) + (cd src ; make all) + (cd lib ; make all) + (cd rep ; make all) + +libs: + (cd inc ; rm -f Mallba) + (cd inc ; ./inc.env) + (cd src ; make all) + (cd lib ; make all) + +skeletons: + (cd rep ; make all) + +clean: + (cd inc ; rm -f Mallba) + (cd src ; make clean) + (cd lib ; make clean) + (cd rep ; make clean) diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/br17.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/br17.atsp new file mode 100644 index 0000000..37313b1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/br17.atsp @@ -0,0 +1,42 @@ +NAME: br17 +TYPE: ATSP +COMMENT: 17 city problem (Repetto) +DIMENSION: 17 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999 3 5 48 48 8 8 5 5 3 3 0 3 5 8 8 + 5 + 3 9999 3 48 48 8 8 5 5 0 0 3 0 3 8 8 + 5 + 5 3 9999 72 72 48 48 24 24 3 3 5 3 0 48 48 + 24 + 48 48 74 9999 0 6 6 12 12 48 48 48 48 74 6 6 + 12 + 48 48 74 0 9999 6 6 12 12 48 48 48 48 74 6 6 + 12 + 8 8 50 6 6 9999 0 8 8 8 8 8 8 50 0 0 + 8 + 8 8 50 6 6 0 9999 8 8 8 8 8 8 50 0 0 + 8 + 5 5 26 12 12 8 8 9999 0 5 5 5 5 26 8 8 + 0 + 5 5 26 12 12 8 8 0 9999 5 5 5 5 26 8 8 + 0 + 3 0 3 48 48 8 8 5 5 9999 0 3 0 3 8 8 + 5 + 3 0 3 48 48 8 8 5 5 0 9999 3 0 3 8 8 + 5 + 0 3 5 48 48 8 8 5 5 3 3 9999 3 5 8 8 + 5 + 3 0 3 48 48 8 8 5 5 0 0 3 9999 3 8 8 + 5 + 5 3 0 72 72 48 48 24 24 3 3 5 3 9999 48 48 + 24 + 8 8 50 6 6 0 0 8 8 8 8 8 8 50 9999 0 + 8 + 8 8 50 6 6 0 0 8 8 8 8 8 8 50 0 9999 + 8 + 5 5 26 12 12 8 8 0 0 5 5 5 5 26 8 8 + 9999 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft53.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft53.atsp new file mode 100644 index 0000000..3f81c5b --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft53.atsp @@ -0,0 +1,220 @@ +NAME: ft53 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 53 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 223 210 125 245 363 322 388 290 341 267 281 258 247 302 + 325 311 276 392 475 417 324 372 437 610 310 362 333 498 459 + 467 352 199 336 305 172 143 273 292 364 262 296 435 423 433 + 354 509 472 238 185 357 420 344 + 58 9999999 179 100 287 155 116 170 74 137 239 260 234 221 282 + 294 286 251 434 512 409 367 406 410 598 354 353 371 451 490 + 510 389 244 313 291 210 185 318 329 402 297 81 241 215 292 + 308 301 262 207 159 300 214 314 + 60 109 9999999 80 295 246 209 270 174 225 227 179 221 212 262 + 131 117 79 382 431 263 309 321 235 452 355 338 324 497 449 + 360 243 251 140 272 223 189 259 337 388 308 174 340 309 382 + 396 393 355 198 141 201 302 190 + 58 115 98 9999999 285 255 215 279 178 232 154 176 157 136 194 + 219 207 170 429 516 326 366 411 323 517 344 270 368 541 498 + 446 323 244 225 203 214 183 314 278 403 301 183 352 311 391 + 341 410 367 130 76 247 312 236 + 93 58 63 90 9999999 194 160 210 117 174 238 235 231 224 280 + 175 171 133 281 267 221 248 139 286 415 82 136 135 309 264 + 341 293 231 189 75 253 219 306 360 351 340 123 277 248 288 + 323 305 256 155 155 152 248 146 + 531 593 584 499 765 9999999 344 405 309 360 631 654 632 622 679 + 697 685 647 909 992 807 847 887 809 999 789 750 848 763 716 + 763 643 724 539 682 687 664 788 762 881 781 669 832 796 824 + 825 885 838 90 140 164 70 296 + 417 484 469 384 651 55 9999999 257 190 180 519 547 524 506 563 + 586 573 533 803 875 693 733 777 692 888 607 577 662 585 539 + 575 454 611 361 561 581 543 682 645 769 666 546 577 565 493 + 662 653 700 123 177 201 112 343 + 466 521 506 427 693 86 111 9999999 236 275 566 585 505 546 552 + 621 618 574 804 863 594 495 733 735 790 695 673 660 675 627 + 674 556 654 453 615 614 587 685 634 715 707 591 673 659 589 + 690 749 771 154 209 228 147 371 + 243 309 285 205 468 92 54 111 9999999 69 342 366 345 326 385 + 406 391 350 619 705 510 552 599 511 707 501 451 558 472 425 + 471 346 432 253 394 393 373 500 468 588 491 369 532 501 535 + 534 591 549 160 210 233 147 376 + 262 321 302 222 491 81 68 99 32 9999999 359 386 357 340 400 + 424 409 371 639 714 536 569 611 528 728 448 415 504 424 376 + 412 296 450 196 407 419 386 521 488 605 503 389 554 521 554 + 550 614 568 151 204 228 137 359 + 361 416 404 317 435 522 512 544 471 449 9999999 194 179 327 228 + 441 438 392 480 560 357 401 554 557 549 502 453 418 596 544 + 655 532 383 455 396 352 319 359 313 475 437 352 453 467 453 + 373 527 531 78 135 308 392 291 + 182 241 229 134 411 376 341 402 302 314 114 9999999 195 184 246 + 304 288 258 499 583 376 420 494 411 568 395 315 433 612 564 + 511 413 364 311 250 333 305 375 322 493 425 306 469 435 466 + 385 531 481 180 202 333 425 319 + 271 305 315 224 271 354 341 374 301 283 110 105 9999999 164 60 + 276 263 233 313 400 186 241 395 389 387 336 283 255 424 378 + 486 361 220 290 224 179 154 197 138 308 273 182 290 308 285 + 203 363 362 179 231 311 399 293 + 216 277 259 176 281 209 199 227 155 140 35 54 24 9999999 77 + 132 125 79 331 411 204 253 329 246 400 225 147 265 443 397 + 346 239 229 140 80 193 163 211 157 322 288 200 296 320 295 + 215 374 380 94 148 163 255 151 + 275 338 327 242 344 300 293 331 256 241 122 119 99 111 9999999 + 230 220 181 400 479 144 197 371 340 337 327 242 204 384 334 + 446 347 295 238 176 265 235 275 223 262 352 140 303 270 346 + 286 363 315 189 242 261 352 252 + 369 329 451 411 404 405 367 422 324 378 345 393 514 539 561 + 9999999 329 297 264 313 405 312 528 446 596 407 358 316 380 448 + 557 432 286 353 460 163 226 141 278 276 244 379 425 443 412 + 335 494 538 86 146 89 188 75 + 246 305 286 204 416 353 317 374 276 331 181 75 266 252 307 + 24 9999999 310 275 324 158 207 225 136 356 337 270 221 398 348 + 471 348 204 368 315 177 238 151 288 279 260 143 307 267 356 + 351 362 316 99 160 103 199 94 + 278 343 325 243 450 390 353 417 315 367 215 115 301 293 349 + 65 48 9999999 308 365 195 243 261 175 388 381 292 260 430 392 + 292 170 237 79 358 217 274 193 327 318 294 184 346 312 394 + 384 405 355 138 192 141 228 127 + 118 85 249 161 356 148 113 176 78 128 250 149 299 284 345 + 70 86 44 9999999 90 226 277 293 204 425 180 241 241 162 363 + 330 210 271 109 355 227 245 198 337 344 306 146 307 275 359 + 379 368 327 146 202 154 216 140 + 134 93 266 176 364 172 137 191 90 153 255 155 317 301 363 + 93 81 62 31 9999999 227 276 291 207 418 102 160 162 82 291 + 341 227 279 118 370 242 261 216 351 351 322 169 325 294 374 + 392 390 338 157 203 151 225 142 + 306 367 350 263 371 212 171 229 139 186 238 142 322 312 365 + 412 417 378 356 371 9999999 64 239 275 207 196 121 84 252 204 + 558 432 285 370 375 226 223 227 248 138 265 351 377 413 389 + 304 409 368 285 285 330 268 310 + 376 460 449 354 466 305 266 323 227 282 336 230 416 408 462 + 448 448 424 389 372 115 9999999 250 262 307 291 225 171 350 306 + 600 483 332 468 472 322 322 327 342 231 361 429 383 426 401 + 407 415 372 356 306 421 370 410 + 136 225 336 245 369 292 264 314 221 277 328 231 387 368 428 + 221 210 191 160 145 101 122 9999999 251 300 235 212 168 211 299 + 472 353 318 248 239 296 266 314 333 230 351 199 149 187 173 + 203 182 141 121 72 239 339 236 + 223 307 374 280 399 233 198 252 158 213 256 160 343 332 388 + 303 298 273 247 226 36 87 96 9999999 233 217 147 100 270 227 + 350 236 84 331 328 242 246 253 264 165 288 280 238 269 255 + 291 268 217 207 156 332 293 320 + 183 267 381 290 407 296 267 319 223 276 329 226 411 402 460 + 256 251 230 200 185 103 92 61 81 9999999 270 219 173 254 297 + 420 302 153 288 278 316 303 319 339 226 352 241 195 232 208 + 245 226 181 171 117 289 363 272 + 598 658 641 559 823 621 644 551 718 780 695 718 695 682 739 + 689 678 707 946 998 734 782 890 806 924 9999999 71 72 244 195 + 729 609 789 715 750 756 721 819 819 857 838 727 689 726 716 + 744 718 675 315 368 321 407 309 + 536 605 586 502 765 567 585 494 669 719 635 657 639 627 680 + 630 622 652 887 942 766 819 831 748 960 105 9999999 158 334 284 + 811 700 726 709 690 692 660 762 768 882 780 666 779 803 799 + 827 813 768 399 460 404 499 396 + 581 646 628 543 812 611 638 542 710 767 687 701 682 673 724 + 675 664 698 925 982 675 727 871 789 866 135 61 9999999 184 141 + 669 547 771 651 722 737 713 809 808 801 833 682 637 677 650 + 688 665 620 257 312 259 348 246 + 620 677 670 581 853 647 655 579 624 677 717 620 716 702 761 + 718 701 734 835 853 498 547 725 763 696 36 99 98 9999999 218 + 500 375 773 479 775 618 711 711 734 621 714 751 713 752 733 + 768 743 701 86 138 91 182 80 + 586 647 632 545 821 614 634 547 663 716 692 668 681 674 735 + 681 672 698 880 896 547 598 773 791 741 85 67 138 63 9999999 + 546 429 780 522 736 662 714 763 778 669 757 715 762 800 781 + 815 796 752 132 184 135 224 119 + 500 712 702 613 737 847 812 871 776 829 756 770 747 737 792 + 812 803 764 879 958 908 814 861 925 1103 797 782 822 987 943 + 9999999 653 691 559 793 659 628 764 774 849 753 784 927 911 917 + 838 998 963 724 677 843 911 833 + 619 720 707 621 850 685 705 614 723 772 764 725 756 746 807 + 758 739 766 883 862 596 502 740 747 791 220 134 281 447 407 + 136 9999999 485 118 815 775 752 815 830 717 853 673 700 620 795 + 721 778 815 520 573 528 621 514 + 768 870 853 766 1000 831 853 762 872 923 905 870 910 892 956 + 904 893 916 1032 1015 742 648 884 901 936 369 279 431 598 551 + 285 166 9999999 262 964 931 898 966 983 866 1000 819 854 775 946 + 870 926 964 669 725 676 766 664 + 722 816 801 722 951 786 805 710 820 873 860 820 859 848 901 + 858 847 875 978 959 702 600 837 852 894 322 232 376 554 510 + 235 119 381 9999999 915 879 852 912 931 825 950 773 797 722 902 + 821 871 923 625 678 621 712 611 + 730 693 861 768 883 538 493 738 678 664 619 759 779 894 825 + 678 689 652 619 706 838 784 898 818 1026 520 435 582 752 705 + 274 316 169 394 9999999 642 698 617 755 754 722 756 896 889 889 + 815 974 932 95 144 99 188 84 + 341 300 311 337 257 375 338 399 305 361 254 374 427 467 474 + 297 306 267 237 315 264 163 384 416 462 291 215 178 349 302 + 461 345 194 332 324 9999999 135 116 137 210 109 238 275 296 272 + 199 358 396 124 73 243 335 231 + 371 325 341 374 292 403 360 425 331 382 139 312 308 451 352 + 323 335 303 266 345 297 195 413 442 485 315 246 204 373 333 + 341 222 81 329 351 48 9999999 142 158 231 133 260 307 322 301 + 226 386 423 152 102 271 366 264 + 247 200 330 286 276 274 236 300 203 257 218 273 383 410 434 + 192 207 168 139 218 282 179 395 324 472 303 231 185 280 321 + 428 309 157 230 334 40 93 9999999 154 158 120 254 293 311 291 + 216 367 408 148 98 269 337 261 + 225 179 195 223 140 320 280 337 249 301 147 321 321 346 367 + 250 264 221 188 268 301 214 265 382 499 203 265 214 337 345 + 361 241 88 277 202 61 23 67 9999999 207 147 117 157 174 152 + 76 238 271 168 116 279 371 268 + 331 288 305 330 253 178 139 379 292 304 221 360 395 459 433 + 289 301 261 227 311 304 206 374 415 491 311 255 215 370 335 + 433 315 166 317 315 96 98 110 125 9999999 144 225 267 285 265 + 188 341 383 215 162 329 241 317 + 250 214 223 255 174 287 245 305 209 262 165 283 335 373 385 + 211 218 177 152 226 170 79 297 331 365 204 132 85 260 207 + 373 256 109 243 234 54 47 26 48 118 9999999 143 188 205 181 + 108 260 306 167 116 279 341 271 + 529 587 576 488 738 428 456 355 574 613 548 618 623 605 669 + 593 602 569 537 613 494 548 561 477 693 403 454 461 380 590 + 556 594 445 628 289 509 566 476 613 616 586 9999999 172 144 227 + 241 232 189 257 204 370 466 358 + 412 441 461 373 592 269 287 194 421 448 495 512 509 497 556 + 437 447 406 373 454 427 480 490 410 628 339 400 398 322 530 + 496 532 381 464 229 360 418 335 464 470 436 61 9999999 107 158 + 135 84 131 212 168 309 323 297 + 393 453 440 353 622 347 370 272 497 527 498 519 495 478 544 + 516 527 488 452 537 459 515 520 442 659 426 478 475 399 606 + 528 560 413 547 261 433 497 410 551 553 515 67 94 9999999 190 + 115 163 211 128 74 245 338 239 + 464 520 508 421 648 353 370 275 401 464 505 407 558 546 605 + 520 533 489 457 478 282 334 346 262 483 425 398 353 401 479 + 343 387 234 464 86 447 497 415 518 408 528 65 98 76 9999999 + 181 170 221 161 147 167 260 152 + 296 360 344 258 527 348 375 276 427 477 394 415 398 385 440 + 462 449 406 459 534 360 410 430 338 552 422 475 426 398 551 + 426 463 315 465 162 442 423 422 526 491 523 50 94 112 94 + 9999999 173 213 226 178 240 330 232 + 339 403 387 301 524 359 387 286 443 495 435 462 436 426 479 + 443 453 409 377 457 354 412 422 331 554 387 443 420 364 546 + 423 456 310 473 160 283 338 264 394 397 369 31 110 29 88 + 58 9999999 184 144 97 240 329 221 + 364 426 411 320 564 276 299 211 425 461 379 445 465 453 511 + 448 460 423 386 469 314 364 378 295 510 220 278 282 203 410 + 383 414 272 478 113 327 383 306 434 443 406 76 26 67 47 + 86 61 9999999 177 134 193 294 184 + 1551 1527 1596 1509 1784 1572 1562 1504 1522 1513 1653 1593 1650 1634 1695 + 1512 1530 1489 1455 1532 1512 1560 1549 1582 1505 1050 1026 1104 1028 978 + 1419 1297 1562 1197 1678 1635 1678 1643 1747 1637 1717 1578 1617 1634 1614 + 1534 1693 1672 9999999 73 233 330 224 + 1599 1569 1649 1566 1834 1527 1515 1543 1478 1463 1706 1641 1621 1687 1673 + 1571 1578 1543 1504 1585 1548 1530 1496 1520 1458 1102 1078 1154 1079 1027 + 1360 1248 1506 1144 1628 1682 1727 1689 1754 1666 1775 1517 1568 1582 1557 + 1486 1638 1621 60 9999999 188 274 169 + 1504 1464 1629 1541 1713 1598 1564 1542 1528 1543 1552 1549 1454 1603 1497 + 1550 1557 1526 1490 1566 1539 1566 1579 1609 1534 1080 1062 1144 1060 1010 + 1192 1071 1343 977 1621 1627 1593 1632 1577 1663 1715 1514 1553 1578 1548 + 1477 1627 1670 44 100 9999999 272 159 + 1505 1534 1545 1464 1705 1550 1572 1487 1533 1523 1607 1601 1548 1586 1590 + 1532 1543 1503 1470 1547 1519 1573 1563 1549 1517 1057 1045 1120 1040 993 + 1280 1168 1432 1060 1366 1462 1581 1563 1584 1648 1551 1255 1302 1319 1298 + 1224 1380 1412 24 79 106 9999999 240 + 1520 1472 1612 1526 1722 1589 1574 1517 1528 1520 1559 1558 1466 1616 1513 + 1530 1536 1501 1466 1544 1517 1573 1562 1593 1518 1056 1044 1116 1036 992 + 1206 1088 1352 986 1469 1571 1607 1642 1595 1643 1658 1362 1411 1429 1401 + 1325 1479 1516 21 80 29 118 9999999 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft70.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft70.atsp new file mode 100644 index 0000000..75cacb6 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ft70.atsp @@ -0,0 +1,358 @@ +NAME: ft70 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 70 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 375 1000 1011 853 950 936 1027 1101 1235 1279 1109 1141 976 1389 + 858 1368 1110 1263 1435 1091 936 1047 962 1079 1083 826 926 1004 1203 + 1037 1105 1229 986 1227 1096 1235 973 753 1165 1518 1064 1285 1149 1312 + 914 1161 1349 1418 1515 1170 966 1112 1049 1064 912 901 1040 1086 1177 + 1118 1239 1103 1203 1094 1237 1143 1195 1293 1229 + 609 9999999 1068 980 1029 976 1068 1144 1100 1342 1262 1097 1304 1217 1494 + 960 1214 1233 1040 1175 1122 1237 1133 1031 1192 1004 1005 1087 1119 1109 + 1019 1087 1248 1257 1196 1061 1284 1142 951 1117 1329 1320 1284 1340 1282 + 934 1207 1200 1559 1717 1190 1168 1213 1144 1196 1317 1112 1048 1259 1008 + 871 1326 1455 977 1139 1335 974 1352 1468 1057 + 669 419 9999999 888 528 955 989 989 794 1185 1055 987 933 1009 1022 + 709 1124 1137 1203 1048 984 845 657 600 880 998 874 739 603 1042 + 939 1024 986 813 1136 872 963 1013 710 801 1189 1126 977 1102 1069 + 683 1102 1253 1316 1373 978 1046 881 998 1001 948 751 982 1092 881 + 829 1335 1082 1071 1053 941 889 1100 1164 970 + 665 645 664 9999999 559 491 528 592 505 769 680 576 793 724 996 + 796 898 755 525 1002 639 629 676 635 694 854 562 543 524 790 + 495 632 968 715 923 665 809 811 496 794 1031 759 714 829 764 + 609 504 1040 903 986 544 703 543 942 814 712 794 546 741 737 + 430 926 1047 660 686 558 632 944 808 890 + 632 606 506 676 9999999 659 742 781 582 926 778 865 868 620 798 + 499 996 787 883 792 858 615 438 483 671 523 527 557 562 661 + 544 609 871 587 837 541 787 571 558 594 1038 910 761 873 765 + 648 651 970 1026 1307 811 669 749 621 548 748 649 697 923 652 + 707 879 968 617 879 706 773 1035 944 863 + 712 373 621 441 416 9999999 441 666 565 524 541 507 803 574 680 + 613 739 875 860 1018 699 697 576 691 801 761 606 511 597 805 + 619 790 808 798 965 654 698 636 676 842 986 886 910 690 897 + 464 556 1062 1178 1097 697 830 869 627 821 661 784 848 868 562 + 623 927 823 544 475 852 674 803 814 786 + 412 702 566 534 473 744 9999999 623 690 765 770 526 699 752 986 + 492 577 596 733 746 598 672 681 715 676 762 608 590 522 782 + 694 769 976 723 700 704 923 692 467 751 964 813 806 818 538 + 485 700 865 996 1234 548 645 766 800 759 606 786 681 651 549 + 482 901 792 702 544 726 456 902 925 827 + 826 666 682 535 668 660 705 9999999 688 861 755 706 766 495 693 + 913 1001 768 727 1046 724 894 748 927 1051 816 863 743 654 822 + 872 952 1094 786 839 968 1126 1039 662 789 1152 1080 798 884 852 + 986 622 1202 1255 1072 813 980 841 984 929 872 868 893 810 876 + 791 1090 1030 708 822 879 577 1058 896 1107 + 874 915 804 786 736 873 725 491 9999999 729 749 578 641 757 747 + 942 943 1023 937 1170 746 1066 943 808 943 893 1064 909 1005 1095 + 803 1046 1041 1079 933 958 1078 1100 820 845 1225 975 971 755 1020 + 956 690 1241 1129 939 820 922 981 1105 961 1136 922 905 956 1001 + 785 1087 1012 905 839 921 753 913 755 981 + 806 919 992 826 940 683 913 470 456 9999999 728 555 653 586 802 + 962 896 1137 811 950 972 1005 797 934 1070 975 857 887 791 1055 + 852 946 1049 983 1037 1094 1111 1122 807 1019 1342 1160 883 814 1119 + 870 932 1124 1364 910 782 1104 1072 1063 938 929 939 926 1084 831 + 864 1151 1137 618 757 828 481 786 740 980 + 773 960 1030 780 702 970 966 697 559 472 9999999 803 609 743 612 + 1100 974 970 970 1162 825 989 910 954 1156 1107 974 1092 1059 908 + 944 1118 1050 1023 1062 975 1172 1154 833 988 1312 1045 1154 592 1182 + 879 815 1097 1368 1193 1001 1106 1003 1026 1130 1007 967 1085 973 922 + 1006 1271 1285 505 737 875 689 1027 842 1123 + 805 663 762 640 787 632 870 475 381 585 501 9999999 628 577 806 + 846 909 1021 880 1087 1009 934 1024 932 905 990 1032 994 847 1121 + 830 911 1138 1018 1134 745 854 851 740 818 965 740 868 514 883 + 968 735 1046 1307 948 694 847 1014 1023 1016 949 1047 882 1138 744 + 844 1307 1154 657 721 856 664 927 730 954 + 910 777 916 662 851 937 745 695 527 528 402 533 9999999 909 669 + 911 1044 1129 938 1099 873 1187 888 956 1193 1126 1172 1026 800 979 + 1119 1041 1235 1154 1195 981 1185 1111 858 1143 1435 1001 1012 833 1205 + 1129 1027 1087 1332 1057 968 1110 849 1089 1207 1026 1111 993 902 1075 + 893 1112 1073 474 624 684 773 1074 750 1060 + 1058 766 1030 850 962 822 865 655 471 625 580 655 608 9999999 703 + 975 1238 1063 991 1213 885 987 1023 942 1137 956 889 923 935 1214 + 1023 1063 1339 983 1046 1040 1025 1180 956 932 1412 906 1006 853 1155 + 871 836 1155 1480 1172 1011 1157 1050 1274 1125 975 950 1092 1001 858 + 795 1295 1039 615 856 948 721 886 799 1149 + 935 773 823 884 766 684 735 663 571 613 479 685 682 643 9999999 + 901 1005 902 877 1117 842 878 963 1038 1156 914 984 1052 999 1176 + 963 1175 1245 942 1114 997 1091 1096 802 990 1247 1022 876 799 949 + 948 890 1137 1274 912 759 898 1094 1040 1175 969 1116 1076 1045 808 + 837 1244 1071 398 656 762 757 998 786 1207 + 647 593 614 715 510 570 622 492 696 670 681 532 710 716 1007 + 9999999 1025 786 989 812 936 662 825 588 842 916 765 563 573 985 + 908 794 825 759 1062 882 1084 794 743 918 1318 931 1050 611 913 + 809 582 742 1357 1068 731 839 816 718 828 975 707 743 830 869 + 897 1194 1054 918 832 723 785 942 910 985 + 675 703 683 693 611 725 910 776 662 870 943 557 856 907 878 + 375 9999999 699 582 560 728 970 601 719 799 831 843 696 625 848 + 718 681 907 695 1005 688 946 811 699 969 1136 716 788 958 656 + 802 709 627 1002 1098 690 559 685 752 689 784 926 790 864 776 + 936 1195 1008 699 845 833 687 940 972 688 + 852 654 736 652 626 608 767 795 635 851 827 876 673 663 692 + 567 555 9999999 760 648 682 734 458 790 645 480 679 676 665 805 + 767 812 845 861 1080 723 838 713 675 777 1154 830 628 974 706 + 608 855 783 976 1245 920 684 781 727 678 600 809 806 817 766 + 871 1144 1058 616 862 762 836 1124 979 729 + 676 602 822 793 723 660 862 636 719 828 885 742 942 880 967 + 492 606 587 9999999 551 710 955 743 877 672 582 785 746 707 821 + 477 502 898 734 958 782 853 577 621 666 1088 883 770 921 868 + 973 877 626 1113 1233 654 709 888 781 941 740 1006 685 675 864 + 902 926 677 808 800 874 931 991 1050 781 + 820 868 737 766 816 800 744 861 631 819 966 775 1015 755 855 + 709 774 617 494 9999999 854 677 563 725 799 482 799 770 742 816 + 506 755 866 710 997 639 856 556 800 771 879 492 692 931 626 + 779 553 526 1047 1112 528 455 754 744 755 483 843 527 636 725 + 836 837 800 932 917 650 831 1038 864 836 + 844 767 714 878 815 561 758 717 752 704 821 642 944 600 808 + 651 662 398 377 793 9999999 780 726 868 582 686 768 937 914 680 + 628 688 762 749 931 745 890 786 747 555 902 872 694 975 763 + 699 816 756 1192 1166 912 868 809 929 994 917 819 654 871 691 + 921 906 796 568 558 711 688 1092 990 912 + 894 676 988 739 891 721 818 957 878 880 788 849 981 721 828 + 806 1065 982 793 913 824 9999999 797 747 545 706 498 582 690 912 + 904 985 972 680 969 620 937 763 775 755 1315 1000 787 988 1119 + 645 770 1092 1354 1337 784 713 829 888 704 664 712 824 932 872 + 707 1022 922 611 867 553 749 1007 773 932 + 721 892 856 716 760 758 739 640 635 787 908 803 876 716 717 + 727 1099 1018 1015 1038 798 492 9999999 574 651 395 666 707 827 927 + 674 995 1005 811 870 544 932 926 914 738 1173 918 984 1028 1123 + 885 685 1145 1252 1354 954 954 765 748 755 742 738 895 836 869 + 975 1179 961 644 737 691 666 1073 743 1067 + 811 753 647 617 776 593 724 835 588 768 645 641 601 745 927 + 434 997 749 658 990 798 550 777 9999999 632 594 483 744 646 644 + 519 609 787 674 909 646 758 609 701 740 1067 657 780 852 788 + 773 612 1035 1194 1225 586 644 514 633 625 505 581 728 848 725 + 917 771 644 536 707 754 640 793 848 876 + 678 604 575 573 490 579 453 828 776 847 727 786 622 630 925 + 672 757 817 646 794 700 630 627 515 9999999 652 611 486 514 598 + 468 775 798 501 727 793 827 811 726 802 1006 692 697 696 943 + 586 675 922 1063 1286 579 707 717 737 682 559 456 710 923 515 + 621 894 792 556 683 409 512 751 647 847 + 731 732 725 489 589 589 680 626 799 712 803 556 656 438 737 + 666 872 817 972 1107 711 656 552 602 514 9999999 765 697 666 670 + 595 745 834 849 855 432 1002 871 869 682 1258 747 712 946 993 + 563 846 1123 1189 1187 835 860 688 846 856 780 678 809 878 712 + 871 1082 1030 756 798 668 589 839 642 790 + 772 738 682 764 816 664 570 905 717 697 860 848 948 547 1005 + 756 991 1006 723 900 799 666 656 646 624 610 9999999 775 651 764 + 687 734 833 626 1018 519 1110 936 871 695 1008 913 950 969 1059 + 776 615 1105 1347 1195 622 733 632 741 717 581 724 762 772 788 + 764 948 879 738 841 774 827 1001 663 938 + 910 887 809 662 731 716 593 859 803 630 677 712 760 547 708 + 628 1054 891 742 867 856 515 331 512 470 531 496 9999999 669 660 + 795 662 777 783 801 656 996 716 750 724 1176 908 752 872 770 + 600 712 882 1081 1311 616 698 615 799 760 764 676 643 640 545 + 858 1006 901 542 685 582 663 1021 936 702 + 908 545 674 582 724 560 725 639 563 628 676 630 602 733 902 + 440 949 750 837 902 801 497 619 561 750 630 492 616 9999999 804 + 476 746 844 730 781 512 864 683 834 623 1008 800 712 703 822 + 452 805 986 977 1197 633 616 575 690 463 555 588 608 675 596 + 978 1029 696 670 782 846 884 838 730 616 + 1085 780 885 770 888 874 926 884 638 611 717 693 577 669 766 + 852 1054 1168 1098 1000 1039 613 663 612 673 748 758 622 712 9999999 + 787 986 879 775 928 787 1129 823 987 775 1338 1010 997 845 862 + 892 916 1174 1191 1161 879 720 973 841 680 698 888 907 801 827 + 998 998 986 519 624 615 780 628 575 596 + 878 696 874 663 770 717 884 655 731 732 732 902 803 960 869 + 500 778 784 861 857 792 885 630 762 761 613 752 690 885 590 + 9999999 838 742 805 716 519 574 406 632 501 925 509 627 924 671 + 716 547 874 1240 1251 516 662 700 809 812 852 788 1006 882 842 + 881 1154 849 557 899 756 683 906 745 646 + 813 784 877 869 876 781 1000 859 706 634 754 805 707 746 843 + 553 822 959 704 833 949 938 822 920 966 816 808 793 784 648 + 370 9999999 670 692 782 511 626 580 693 589 991 506 698 870 649 + 842 557 1083 945 1276 576 587 698 957 904 1055 972 744 529 728 + 644 854 526 676 903 695 669 858 668 701 + 651 673 934 789 845 801 764 715 548 747 612 704 451 772 786 + 642 1139 871 941 960 797 811 566 708 687 632 597 458 945 437 + 530 661 9999999 633 664 617 743 643 636 596 960 572 791 635 543 + 830 621 957 801 1228 802 802 874 825 886 944 873 728 593 677 + 976 922 664 742 608 676 755 600 693 421 + 929 854 813 724 841 643 752 877 605 730 710 834 647 690 1005 + 492 1060 804 895 938 718 972 667 849 704 740 877 645 746 514 + 475 423 475 9999999 589 543 730 578 609 667 978 586 662 795 697 + 778 750 982 886 1100 759 535 802 813 871 921 1022 809 605 602 + 707 873 678 732 903 753 683 683 656 671 + 755 447 1127 804 1000 723 994 736 822 832 875 733 776 786 766 + 778 957 916 992 1118 932 801 826 680 994 749 756 787 999 623 + 636 564 458 684 9999999 824 757 611 868 726 1103 815 615 992 711 + 845 768 1137 853 1159 891 792 862 842 834 895 875 962 788 602 + 850 810 801 778 879 898 664 874 878 686 + 1858 1976 1887 1686 1781 1843 1899 1634 1777 1688 1743 1598 1732 1402 1622 + 1612 2196 2109 2183 2035 1905 2180 1912 1921 1990 2028 2069 1981 1926 1987 + 2098 2050 1948 2016 1931 9999999 1262 1205 1130 1200 1605 1232 1167 1689 1926 + 2031 1923 2276 2160 2197 1858 1820 1924 1965 1932 1846 2129 1716 1877 1731 + 1769 2022 2157 1179 1230 1366 1386 1452 1320 1302 + 1023 1198 1259 1228 1416 1113 1340 1334 1089 1213 1244 1135 1397 914 1167 + 1038 1399 1487 1368 1555 1444 1164 1179 1341 1207 1362 1318 1267 1166 1195 + 1360 1142 1318 1300 1313 642 9999999 570 692 492 845 626 451 1350 1235 + 1232 1202 1404 1647 1647 1182 1040 1242 1281 1253 1205 1376 1280 1191 1120 + 1173 1432 1339 727 734 847 820 822 718 557 + 1203 1180 1235 1260 1198 1296 1196 1297 1266 1350 1316 1346 1498 1353 1361 + 1120 1501 1386 1508 1532 1483 1369 1348 1271 1430 1305 1405 1210 1393 1494 + 1353 1596 1381 1423 1319 742 864 9999999 786 711 1009 841 876 1334 1284 + 1408 1321 1587 1572 1730 1453 1323 1424 1514 1339 1376 1518 1095 1103 1095 + 947 1540 1562 515 819 601 716 649 648 526 + 1137 1280 1415 1140 1466 1182 1287 1125 1146 1204 1134 1012 1215 788 1310 + 1290 1483 1543 1527 1605 1548 1426 1418 1461 1494 1605 1516 1484 1438 1644 + 1347 1455 1452 1311 1481 530 787 731 9999999 558 1148 886 719 1126 1300 + 1458 1332 1705 1571 1622 1521 1289 1388 1339 1421 1326 1425 1185 1349 1149 + 1148 1646 1506 874 974 697 789 812 965 653 + 1044 962 1287 1247 1101 1285 1134 1081 1249 1282 1241 1225 1197 1129 1382 + 1128 1326 1264 1422 1308 1409 1197 1215 1096 1038 1190 1330 1210 1147 1424 + 1229 1126 1325 1315 1466 650 702 332 576 9999999 712 403 448 1354 1125 + 1256 1268 1409 1514 1535 1239 1018 1029 1219 1127 1140 1347 1217 1202 1277 + 944 1469 1354 614 648 572 675 754 838 514 + 1071 1028 1447 1400 1224 1301 1366 1154 1187 1060 1056 1278 1224 1152 1141 + 1110 1471 1481 1432 1546 1213 1158 1123 1050 1148 1047 1159 1127 1214 959 + 1067 1112 925 1170 1050 671 548 682 583 547 9999999 747 650 1060 861 + 708 1233 1670 1196 1380 1110 1214 1230 1144 1313 1159 1207 1138 1069 1158 + 1045 1409 1022 645 951 700 897 718 810 751 + 1050 882 1342 1161 1325 1217 1275 1168 1197 1192 1178 1299 1322 1062 1302 + 1131 1501 1478 1236 1330 1422 1063 1244 931 954 1228 1073 1092 1210 1338 + 1333 1161 1191 1241 1280 811 515 464 601 721 673 9999999 580 1322 1111 + 1156 1295 1583 1473 1836 1096 1289 1372 1242 1128 1113 1277 1091 1258 1215 + 928 1601 1381 553 604 827 763 752 607 602 + 1118 1166 1415 1307 1108 1232 1357 1272 1258 1393 1412 1346 1249 1158 1211 + 1082 1498 1420 1245 1451 1139 1208 1146 1007 965 1377 1144 1251 1092 1159 + 1167 1169 1378 1072 1209 569 648 652 700 699 722 349 9999999 1288 1274 + 1108 1056 1375 1471 1755 1239 1157 1095 1104 1176 1096 1378 1110 1231 1050 + 1253 1566 1279 684 600 690 753 896 824 490 + 1120 1026 1104 1029 1039 1144 875 1148 1176 1140 1117 944 1065 1279 1132 + 1079 1329 1250 1270 1470 1094 1095 973 1079 1243 1148 1235 988 1039 807 + 953 912 1069 1152 879 989 1326 1181 1080 1152 1508 1097 1254 9999999 1029 + 1282 967 1259 1103 762 1172 1106 1289 1155 1229 1137 1257 1157 1211 1087 + 1035 1381 1100 713 582 646 679 705 638 814 + 1369 1236 1472 1205 1340 1223 1195 1303 1266 1524 1284 1353 1294 1243 1534 + 1132 1252 1399 1376 1400 1504 1185 1081 1080 1336 1235 1127 965 1366 1145 + 1379 1342 1244 1257 1159 1023 1543 1256 1457 1439 1619 1341 1464 765 9999999 + 1251 937 1100 770 937 1185 1213 1297 1468 1344 1258 1387 1377 1352 1221 + 1439 1551 1341 783 794 837 971 896 818 1223 + 1562 1364 1372 1207 1311 1293 1237 1450 1295 1368 1284 1359 1349 1471 1459 + 1602 1502 1487 1531 1802 1496 1493 1363 1448 1562 1356 1530 1300 1568 1290 + 1311 1225 1346 1614 1272 1113 1509 1429 1372 1459 1608 1528 1451 821 1126 + 9999999 1261 1616 1183 1039 1341 1539 1586 1500 1561 1585 1420 1221 1005 1231 + 1323 1135 1045 883 937 1058 981 1022 842 1098 + 1663 1689 1725 1516 1698 1648 1597 1522 1702 1575 1471 1725 1775 1839 1556 + 1778 1900 1901 1845 1982 1753 1932 1593 1793 1768 1808 1694 1732 1700 1705 + 1616 1638 1589 1964 1692 1593 1727 1624 1691 1833 1787 1547 1663 935 1285 + 639 9999999 1559 1194 1452 1645 1659 1879 1792 1793 1757 1775 1413 1283 1377 + 1409 1456 1211 1301 1260 1246 1203 1182 1215 1502 + 1207 1142 1416 1333 1350 1096 1469 1331 1341 1332 1410 1418 1320 1257 1638 + 1404 1293 1419 1272 1332 1318 1518 1288 1272 1403 1328 1482 1452 1402 1086 + 1186 1338 1364 978 1246 1238 1384 1239 1298 1172 1521 1398 1248 967 1429 + 1175 1042 9999999 1055 1124 1039 1181 1235 1126 1238 971 1373 1390 1259 1411 + 1277 1448 1192 1210 1120 1181 1138 1335 1176 1215 + 1080 1222 1165 1152 1249 1021 974 1077 1082 1231 1338 1172 1072 1394 1483 + 1154 915 1295 1308 1203 1272 1143 1187 1058 1309 1164 1058 1304 1248 1046 + 1127 1034 1160 1227 1127 931 1474 1106 1127 1234 1597 1225 1238 398 1065 + 906 791 1011 9999999 841 1112 1254 1240 1325 1411 1294 1387 1147 1209 1187 + 1076 1350 1169 829 685 838 634 827 601 1021 + 1220 1228 1212 1160 1249 1025 1072 943 843 1070 913 1120 1022 1014 857 + 1410 1417 1291 1131 1561 1193 1271 1241 1199 1450 1411 1352 1226 1209 986 + 1194 1152 1041 1327 1072 550 1437 1123 1260 1166 1555 1361 1309 571 1249 + 1292 1123 765 791 9999999 1043 1133 1215 1467 1472 1387 1274 1205 1152 1302 + 1155 1467 1234 839 531 806 698 680 720 1023 + 885 859 1096 981 946 697 832 762 749 852 779 875 995 769 838 + 781 697 536 491 743 655 870 615 796 746 719 891 983 881 947 + 847 700 1057 627 1040 606 785 628 672 821 1151 777 781 1053 945 + 939 799 880 1149 1217 9999999 734 612 641 787 762 731 787 939 995 + 830 1077 821 579 903 717 875 1145 870 684 + 1035 921 1037 989 943 922 1038 886 858 1008 1056 852 1085 931 1017 + 725 863 857 642 877 723 996 781 970 926 850 977 935 1041 855 + 973 806 880 731 1173 786 988 844 765 951 1120 936 831 1147 1073 + 709 513 1082 1269 1397 455 9999999 761 682 911 859 822 1071 949 914 + 1180 928 992 866 810 891 685 1151 1144 785 + 769 779 788 757 686 749 800 793 930 793 913 690 965 526 837 + 679 953 882 639 983 847 587 624 657 708 503 807 888 738 929 + 676 888 859 798 818 703 931 594 631 866 1043 984 669 996 976 + 753 578 1144 1078 1291 535 525 9999999 716 586 573 600 810 813 776 + 927 1135 916 831 811 864 958 1063 835 578 + 723 663 638 515 582 691 689 738 744 828 936 626 842 698 1059 + 598 829 756 656 981 636 640 627 606 774 550 601 554 784 745 + 610 873 974 648 893 618 866 585 471 807 1138 803 742 684 1011 + 779 707 938 1154 1056 617 540 506 9999999 686 788 914 877 965 762 + 831 1078 997 752 856 694 717 898 908 690 + 753 653 755 855 820 700 852 884 903 878 562 874 759 772 759 + 960 848 930 839 1024 661 873 664 707 629 764 954 943 691 939 + 839 861 1012 748 907 853 891 792 660 741 1217 1039 912 945 591 + 868 773 1071 994 1228 605 566 381 563 9999999 759 686 482 736 513 + 752 999 810 851 957 967 725 1131 909 685 + 649 622 595 759 775 682 844 678 630 823 826 676 898 573 1009 + 761 669 738 681 888 641 840 580 710 777 511 688 716 808 523 + 433 658 742 641 899 662 727 656 690 648 824 707 642 954 653 + 907 676 818 936 1102 407 390 645 482 560 9999999 865 701 774 776 + 911 746 846 672 626 794 693 805 829 585 + 739 602 661 823 656 690 849 719 676 486 494 695 487 755 758 + 562 719 687 789 756 635 743 648 762 765 562 779 833 788 637 + 490 661 641 395 724 711 673 754 619 568 1014 559 536 802 656 + 647 654 986 867 1145 360 545 561 408 457 417 9999999 669 678 637 + 866 901 713 466 590 890 546 945 772 572 + 807 776 908 1020 667 1005 973 912 861 1184 1074 989 1111 1025 1102 + 833 1235 1076 1128 1235 1068 959 677 682 981 952 977 660 793 882 + 758 867 1157 946 1085 956 1118 984 715 892 1172 1190 1005 713 476 + 873 1042 1351 790 1078 1069 783 978 1030 1009 798 764 9999999 675 992 + 1150 1146 1048 859 997 947 789 978 798 1035 + 1047 1017 869 1092 940 1142 985 1163 1165 1249 1064 1303 1003 857 1263 + 843 1229 1183 1188 1192 1164 917 847 861 898 840 862 801 834 1051 + 1035 961 1283 1104 1152 1047 1259 1083 1020 971 1529 1078 1268 889 760 + 1074 1244 1282 939 1191 1053 1097 1154 1020 1117 1191 897 676 9999999 909 + 1120 1207 1040 937 965 927 965 1041 871 1276 + 1081 904 825 949 716 1083 990 847 762 760 496 877 949 1036 930 + 838 909 1029 844 1127 1095 825 914 1019 977 1011 881 861 880 1128 + 1026 833 977 1025 887 1122 1063 1136 939 918 1408 911 1040 800 621 + 1072 1012 1237 1070 1103 914 934 990 1063 900 1165 1056 496 584 9999999 + 698 963 854 749 800 797 695 1126 906 1063 + 1006 952 726 975 904 1099 970 718 724 717 792 865 1091 947 799 + 1019 986 1153 817 962 1142 821 753 947 1049 854 1037 771 990 849 + 997 762 876 887 706 1021 1048 951 815 1010 1139 945 849 735 540 + 830 1132 1224 873 1185 1030 1111 914 997 1145 1084 1019 657 701 503 + 9999999 778 818 489 568 766 516 1044 925 782 + 1050 835 996 835 678 941 962 816 678 689 674 941 1082 1102 939 + 940 806 980 730 1033 897 948 938 744 874 771 851 887 816 1099 + 854 946 871 890 877 921 763 792 777 763 974 649 786 836 649 + 926 988 1233 1064 1136 964 878 911 720 668 945 1075 536 538 521 + 718 9999999 890 679 736 761 574 1004 940 774 + 962 1085 996 1061 875 1138 910 891 667 805 532 810 936 1081 835 + 872 885 1005 724 1038 1104 932 725 961 1082 869 985 773 796 1099 + 1085 877 1078 1011 778 957 867 762 795 935 1018 826 816 782 577 + 1090 1033 1010 839 1271 1019 1040 1051 968 862 1025 967 433 389 404 + 679 498 9999999 686 850 801 816 1138 902 821 + 1927 1983 1997 1959 2157 2170 2045 2221 2159 2159 2264 2231 2046 1910 2335 + 2056 1966 1987 2199 1989 2150 1950 2147 2255 2087 1995 2160 2226 2154 2039 + 2188 2019 1977 2218 2043 1606 1494 1604 1558 1461 1832 1398 1580 1490 1921 + 1875 1859 1955 1418 1962 1990 2011 2198 2146 2312 2146 2251 2255 2335 2273 + 1991 2373 2181 9999999 486 752 415 1018 923 916 + 2129 2282 2240 2197 2273 2185 2270 2203 2402 2253 2413 2255 2321 2107 2259 + 2100 2034 2205 2269 2219 2272 1814 2239 2166 2161 2217 2002 2092 1996 2253 + 2289 2170 2251 2071 2307 1728 1627 1569 1622 1533 1960 1795 1579 1787 2181 + 2233 1937 1875 1408 1993 2240 2289 2217 2316 2263 2346 2263 2179 2266 2332 + 2320 2588 2275 691 9999999 978 787 1209 881 963 + 1923 1990 2082 1882 1829 2080 1929 1977 2138 2100 2001 1977 2120 1947 2141 + 1944 1927 1964 2176 2114 2267 1893 1869 2108 2138 1996 1960 1994 2081 2130 + 2058 1978 2068 2200 2045 1592 1451 1525 1531 1474 1911 1520 1660 1526 2080 + 1956 1578 1999 1565 1918 2259 2279 2017 2238 2231 2088 2038 2067 1866 2106 + 2195 2452 2069 471 566 9999999 433 645 552 719 + 2271 2110 2196 2019 2099 2085 2033 2056 2015 2050 2189 2107 1949 2157 2134 + 2041 2197 2053 2072 1750 2205 2042 2120 2107 1977 1940 2022 2106 2040 1906 + 1854 2049 1808 2076 2052 1577 1404 1441 1507 1539 1976 1675 1460 1687 2010 + 2212 1746 1956 1659 2021 1959 1995 1995 1916 2095 1960 2185 1916 1993 2040 + 2181 2270 2134 463 443 618 9999999 909 816 871 + 2170 2021 2292 1997 2202 2012 2037 2216 2244 2226 2018 2067 2008 2096 2295 + 2040 2053 2053 2003 2067 1978 2182 2142 2157 2151 2089 2183 1900 2175 1963 + 2121 2044 2065 1883 2122 1473 1527 1532 1468 1613 1794 1644 1634 1441 1840 + 2122 1932 2006 1403 1761 1915 1889 1926 1994 1983 1999 2031 1926 1662 2008 + 2318 2310 2285 386 627 627 759 9999999 712 749 + 2243 2278 2112 2059 2217 2099 2293 2166 2311 2106 2136 2348 1952 1959 2380 + 2041 2253 1954 2053 1801 2215 2009 2104 2283 2228 2008 1935 2167 2264 2064 + 2026 2138 1856 2037 1875 1612 1581 1757 1682 1713 1918 1738 1632 1726 2061 + 2041 1934 2100 1601 2052 2200 2048 2068 1979 2066 1989 2081 1967 1715 2213 + 2352 2395 2113 588 640 641 461 682 9999999 757 + 2058 2030 2049 2062 2021 2048 2033 2126 2328 2299 2170 2276 2164 1985 2236 + 2245 2137 1972 2182 1902 2327 2130 2046 2237 2246 2273 2163 2031 2267 1981 + 2073 2057 1955 2224 2130 1673 1669 1563 1658 1645 1853 1785 1729 1714 1988 + 2230 1766 1910 1507 1817 2175 2111 2024 2289 2177 2214 2080 1984 1770 2042 + 2173 2271 2101 689 522 613 514 589 663 9999999 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv170.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv170.atsp new file mode 100644 index 0000000..22a978b --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv170.atsp @@ -0,0 +1,4882 @@ +NAME: ftv170 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 171 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 100000000 9 15 19 39 50 + 67 55 75 58 67 85 + 99 100 95 111 125 110 + 103 91 100 109 123 134 + 156 130 143 153 140 126 + 144 132 122 121 111 99 + 112 84 78 88 100 134 + 159 119 125 115 126 137 + 150 51 65 80 91 105 + 148 127 167 180 167 98 + 85 100 188 134 153 132 + 119 117 104 115 140 67 + 47 35 49 68 79 22 + 35 29 22 13 40 82 + 94 133 140 127 141 123 + 130 106 97 85 115 131 + 128 95 114 109 127 143 + 131 143 89 82 74 61 + 67 49 29 21 39 58 + 72 77 90 101 109 127 + 137 136 152 165 111 96 + 85 78 140 131 91 91 + 46 59 69 106 128 138 + 118 132 134 85 86 111 + 122 176 159 128 142 115 + 140 106 91 153 112 127 + 107 114 117 115 123 147 + 158 122 67 109 76 124 + 60 68 45 9 100000000 6 + 26 46 57 74 62 82 + 65 74 76 90 104 102 + 118 132 114 94 82 91 + 100 114 125 147 137 134 + 144 131 117 135 123 113 + 112 102 90 103 75 69 + 79 91 125 150 110 116 + 106 117 128 141 42 56 + 71 82 96 139 118 158 + 171 158 89 76 91 179 + 125 144 123 110 108 95 + 118 131 58 38 26 40 + 59 86 13 26 38 31 + 22 34 91 103 136 143 + 136 150 132 139 115 106 + 94 124 140 137 104 123 + 118 136 152 140 152 98 + 91 83 70 76 58 38 + 30 48 67 81 86 99 + 110 118 136 146 145 161 + 174 120 105 94 87 149 + 140 100 100 55 68 78 + 115 137 147 127 141 141 + 94 93 118 129 185 168 + 135 149 122 147 113 98 + 162 121 118 98 105 108 + 122 130 154 167 131 76 + 118 85 115 51 75 36 + 15 6 100000000 20 40 51 + 68 56 76 59 68 82 + 96 101 96 112 126 111 + 100 88 97 106 120 131 + 153 131 140 150 137 123 + 141 129 119 118 108 96 + 109 81 75 85 97 131 + 156 116 122 112 123 134 + 147 48 62 77 88 102 + 145 124 164 177 164 95 + 82 97 185 131 150 129 + 116 114 101 124 137 64 + 44 32 46 65 80 19 + 32 44 37 28 40 97 + 109 142 149 142 156 138 + 145 121 112 100 130 146 + 143 110 129 124 142 158 + 146 158 104 97 89 76 + 82 64 44 36 54 73 + 87 92 105 116 124 142 + 152 151 167 180 126 111 + 100 93 155 146 106 100 + 61 68 78 121 143 151 + 133 147 135 94 87 112 + 123 191 174 129 143 116 + 141 107 92 168 127 124 + 104 111 114 116 124 148 + 173 137 82 124 91 121 + 57 69 42 75 66 60 + 100000000 20 31 48 36 56 + 39 48 112 126 81 76 + 92 106 91 102 112 118 + 109 123 134 156 111 140 + 153 140 126 144 149 126 + 160 168 156 144 141 135 + 145 157 190 215 176 182 + 172 183 194 207 108 122 + 137 148 162 205 184 224 + 237 224 155 142 157 245 + 190 209 188 175 161 161 + 151 177 124 104 92 76 + 95 60 79 92 104 97 + 88 100 118 130 169 176 + 163 177 159 166 142 133 + 121 151 167 164 131 150 + 145 163 179 167 179 125 + 118 110 97 103 85 65 + 57 75 94 108 113 126 + 137 145 163 173 172 188 + 201 147 132 121 114 160 + 151 127 80 82 48 58 + 142 141 131 148 162 115 + 74 67 92 103 196 179 + 109 123 96 121 87 72 + 189 148 184 164 161 131 + 96 104 128 194 158 103 + 145 112 168 117 49 102 + 55 46 40 53 100000000 11 + 28 16 36 19 28 92 + 106 61 56 72 86 71 + 82 92 98 89 103 114 + 136 91 120 133 120 106 + 124 129 106 140 148 136 + 124 121 115 125 137 170 + 195 156 162 152 163 174 + 187 88 102 117 128 142 + 185 164 204 217 204 135 + 122 137 225 170 189 168 + 155 141 141 131 157 104 + 84 72 56 75 40 59 + 72 84 77 68 80 98 + 110 149 156 143 157 139 + 146 122 113 101 131 147 + 144 111 130 125 143 159 + 147 159 105 98 90 77 + 83 65 45 37 55 74 + 88 93 106 117 125 143 + 153 152 168 181 127 112 + 101 94 140 131 107 60 + 62 28 38 122 121 111 + 128 142 95 54 47 72 + 83 176 159 89 103 76 + 101 67 52 169 128 164 + 144 141 111 76 84 108 + 174 138 83 125 92 148 + 97 29 82 47 56 62 + 42 62 100000000 56 66 86 + 81 90 132 146 111 106 + 122 136 121 132 138 147 + 139 153 164 186 141 170 + 183 170 156 174 179 156 + 168 158 146 159 131 125 + 135 147 181 206 166 172 + 162 173 184 197 98 112 + 127 138 152 195 174 193 + 215 214 145 132 147 223 + 159 178 157 144 130 151 + 120 146 114 94 82 96 + 115 102 69 82 76 69 + 60 87 87 99 138 145 + 132 146 128 135 111 102 + 90 120 136 133 100 119 + 114 132 148 136 148 94 + 87 79 66 72 54 34 + 26 44 63 77 82 95 + 106 114 132 142 141 157 + 170 116 101 90 83 145 + 136 96 49 51 17 27 + 111 133 139 123 137 123 + 43 75 100 111 181 164 + 117 131 104 129 95 80 + 158 117 174 154 161 161 + 126 112 136 163 127 72 + 114 81 137 107 18 92 + 82 73 67 87 72 83 + 100000000 10 30 46 55 119 + 133 55 50 66 80 65 + 76 86 92 83 97 108 + 130 85 114 127 114 100 + 118 123 100 134 155 158 + 118 117 137 147 159 164 + 189 183 184 174 185 196 + 209 115 129 144 155 169 + 212 191 231 244 231 162 + 149 164 252 198 217 196 + 183 181 168 191 204 131 + 111 99 83 102 67 86 + 99 111 104 95 107 164 + 176 209 216 209 223 205 + 212 188 179 167 197 212 + 210 176 195 190 208 224 + 182 194 140 163 156 143 + 149 131 111 103 121 109 + 151 128 141 152 160 178 + 188 187 203 216 162 147 + 136 129 131 122 142 94 + 113 100 72 131 112 102 + 119 133 86 56 38 63 + 74 167 150 80 94 67 + 73 39 24 235 194 176 + 165 135 105 70 56 99 + 209 203 118 190 158 188 + 124 101 109 72 63 57 + 77 62 73 90 100000000 20 + 36 45 109 123 45 40 + 56 70 55 66 76 82 + 73 87 98 120 75 104 + 117 104 90 108 113 90 + 124 145 148 108 107 127 + 137 149 154 179 173 174 + 164 175 186 199 105 119 + 134 145 159 202 181 221 + 234 221 152 139 154 242 + 188 207 186 173 171 158 + 181 194 121 101 89 73 + 92 57 76 89 101 94 + 85 97 154 166 199 206 + 199 213 195 202 178 169 + 157 187 203 200 167 186 + 181 199 215 203 215 161 + 154 146 133 139 121 101 + 93 111 130 144 149 162 + 173 181 199 209 208 224 + 237 183 168 157 150 184 + 175 163 122 118 90 100 + 178 165 155 172 186 139 + 109 91 116 127 220 203 + 133 147 120 96 62 77 + 225 184 166 155 125 95 + 60 79 129 230 194 139 + 181 148 178 114 91 99 + 52 43 37 57 42 53 + 70 58 100000000 16 25 89 + 103 25 20 36 50 35 + 46 56 62 53 67 78 + 100 55 84 97 84 70 + 88 93 70 104 125 128 + 88 87 107 117 129 134 + 159 153 154 144 155 166 + 179 85 99 114 125 139 + 182 161 201 214 201 132 + 119 134 222 168 187 166 + 153 151 138 161 174 101 + 81 69 53 72 37 56 + 69 81 74 65 77 134 + 146 179 186 179 193 175 + 182 158 149 137 167 183 + 180 147 166 161 179 195 + 183 195 141 134 126 113 + 119 101 81 73 91 110 + 124 129 142 153 161 179 + 189 188 204 217 163 148 + 137 130 164 155 143 102 + 98 70 80 158 145 135 + 152 166 119 89 71 96 + 107 200 183 113 127 100 + 76 42 57 205 164 146 + 135 105 75 40 59 109 + 210 174 119 161 128 158 + 94 71 79 36 27 21 + 41 26 37 54 42 62 + 100000000 9 73 87 87 82 + 98 112 97 91 79 88 + 97 111 122 144 117 131 + 141 128 114 132 133 110 + 139 129 117 118 102 96 + 106 118 152 177 137 143 + 133 144 155 168 69 83 + 98 109 123 166 145 185 + 198 185 116 103 118 206 + 152 171 150 137 135 122 + 145 158 85 65 53 37 + 56 21 40 53 65 58 + 49 61 118 130 163 170 + 163 177 159 166 142 133 + 121 151 167 164 131 150 + 145 163 179 167 179 125 + 118 110 97 103 85 65 + 57 75 94 108 113 126 + 137 145 163 173 172 188 + 201 147 132 121 114 166 + 157 127 86 82 54 64 + 142 147 137 154 168 121 + 80 73 98 109 202 185 + 115 129 102 127 93 78 + 189 148 145 125 132 105 + 102 110 134 194 158 103 + 145 112 142 78 55 63 + 188 179 185 205 225 236 + 253 229 249 244 100000000 64 + 78 92 230 149 120 102 + 82 70 79 88 102 113 + 135 146 122 132 119 105 + 123 124 101 133 154 145 + 109 104 124 134 146 163 + 188 188 171 161 172 183 + 196 137 151 166 177 191 + 217 196 236 249 236 184 + 196 211 257 245 251 243 + 230 228 215 238 251 187 + 167 153 28 47 12 166 + 179 198 205 201 187 270 + 268 256 263 265 293 311 + 318 294 285 273 303 319 + 316 283 302 297 315 331 + 319 331 277 270 262 249 + 255 237 217 209 227 246 + 260 265 278 289 297 315 + 325 324 340 353 299 284 + 273 266 310 301 279 279 + 234 247 257 294 291 281 + 298 312 273 254 236 261 + 261 346 329 259 232 205 + 174 208 222 305 300 173 + 153 126 96 153 191 207 + 346 310 255 297 264 235 + 158 254 143 146 137 143 + 163 183 194 211 187 207 + 202 10 100000000 14 28 188 + 107 78 38 18 28 37 + 46 60 71 93 104 80 + 90 77 63 81 82 59 + 91 112 103 67 62 82 + 92 104 121 146 146 129 + 119 130 141 154 95 109 + 124 135 149 175 154 194 + 207 194 142 154 169 215 + 203 209 201 188 186 173 + 196 209 145 125 111 38 + 57 22 124 137 156 163 + 159 145 228 226 214 221 + 223 251 269 276 252 243 + 231 261 277 274 241 260 + 255 273 289 277 289 235 + 228 220 207 213 195 175 + 167 185 204 218 223 236 + 247 255 273 283 282 298 + 311 257 242 231 224 268 + 259 237 237 192 205 215 + 252 249 239 256 270 231 + 212 194 219 219 304 287 + 217 190 163 132 166 180 + 263 258 131 111 84 54 + 111 149 165 304 268 213 + 255 222 193 116 212 101 + 138 129 135 155 175 186 + 203 179 199 194 92 82 + 100000000 14 180 99 70 24 + 10 20 29 38 52 63 + 85 96 72 82 69 55 + 73 74 51 83 104 95 + 59 54 74 84 96 113 + 138 138 121 111 122 133 + 146 87 101 116 127 141 + 167 146 186 199 186 134 + 146 161 207 195 201 193 + 180 178 165 188 201 137 + 117 103 117 65 104 116 + 129 148 155 151 137 220 + 218 206 213 215 243 261 + 268 244 235 223 253 269 + 266 233 252 247 265 281 + 269 281 227 220 212 199 + 205 187 167 159 177 196 + 210 215 228 239 247 265 + 275 274 290 303 249 234 + 223 216 260 251 229 229 + 184 197 207 244 241 231 + 248 262 223 204 186 211 + 211 296 279 209 182 155 + 124 158 172 255 250 123 + 103 76 46 103 141 157 + 296 260 205 247 214 185 + 108 204 93 146 137 143 + 163 183 194 211 169 189 + 202 100 90 104 100000000 170 + 89 60 10 21 31 37 + 28 42 53 75 86 62 + 72 59 45 63 68 45 + 79 100 103 63 62 82 + 92 104 109 134 146 129 + 119 130 141 154 95 109 + 124 135 149 175 154 194 + 207 194 142 154 169 215 + 203 209 201 188 186 173 + 196 209 145 125 111 125 + 73 112 124 137 156 163 + 159 145 228 226 214 221 + 223 251 269 276 252 243 + 231 261 277 274 241 260 + 255 273 289 277 289 235 + 228 220 207 213 195 175 + 167 185 204 218 223 236 + 247 255 273 283 282 298 + 311 257 242 231 224 250 + 241 237 232 192 205 210 + 250 231 221 238 252 213 + 194 176 201 201 286 269 + 199 172 145 114 148 162 + 263 258 121 110 80 50 + 93 131 147 304 268 213 + 255 222 193 116 212 101 + 115 106 100 120 105 116 + 91 43 63 79 88 95 + 109 5 100000000 16 30 15 + 26 36 42 33 47 58 + 80 35 64 77 64 50 + 68 73 50 84 105 108 + 68 67 87 97 109 114 + 139 151 134 124 135 146 + 159 100 114 129 140 154 + 180 159 199 212 199 147 + 159 174 220 208 214 206 + 193 191 178 201 214 150 + 130 116 116 78 100 119 + 132 144 137 128 140 197 + 209 219 226 228 256 238 + 245 221 212 200 230 225 + 238 189 208 203 221 237 + 195 207 153 176 189 176 + 182 164 144 136 154 122 + 164 141 154 165 173 191 + 201 200 216 229 175 160 + 149 142 144 135 155 107 + 126 133 85 144 125 115 + 132 146 99 69 51 76 + 87 180 163 93 107 80 + 56 22 37 268 227 126 + 115 85 55 20 39 89 + 222 216 131 203 191 198 + 121 134 106 164 155 159 + 179 164 175 149 102 122 + 138 118 108 122 20 103 + 100000000 14 28 39 49 55 + 46 60 57 79 19 48 + 61 74 63 81 86 63 + 97 118 121 81 80 100 + 110 122 127 152 164 147 + 137 148 159 172 113 127 + 142 153 167 193 172 212 + 225 212 160 172 187 233 + 221 227 219 206 204 191 + 214 227 163 143 129 143 + 91 130 142 155 174 181 + 177 163 246 244 232 239 + 241 269 287 294 270 261 + 249 279 283 292 247 266 + 261 279 295 253 265 211 + 234 238 225 231 213 193 + 185 203 180 222 199 212 + 223 231 249 247 240 256 + 273 215 218 207 200 183 + 174 198 165 184 192 143 + 183 164 154 171 185 146 + 127 109 134 134 219 202 + 132 105 78 47 81 95 + 281 276 139 128 98 68 + 4 64 80 280 274 189 + 261 240 211 134 193 119 + 150 141 147 167 187 198 + 215 173 193 206 104 94 + 108 113 174 93 100000000 14 + 25 35 41 32 46 57 + 79 90 66 76 63 49 + 67 72 49 83 104 107 + 67 66 86 96 108 113 + 138 150 133 123 134 145 + 158 99 113 128 139 153 + 179 158 198 211 198 146 + 158 173 219 207 213 205 + 192 190 177 200 213 149 + 129 115 129 77 116 128 + 141 160 167 163 149 232 + 230 218 225 227 255 273 + 280 256 247 235 265 281 + 278 245 264 259 277 293 + 281 293 239 232 224 211 + 217 199 179 171 189 208 + 222 227 240 251 259 277 + 287 286 302 315 261 246 + 235 228 254 245 241 236 + 196 209 214 254 235 225 + 242 256 217 198 180 205 + 205 290 273 203 176 149 + 118 152 166 267 262 125 + 114 84 54 97 135 151 + 308 272 217 259 226 197 + 120 216 105 136 127 133 + 153 173 184 201 159 179 + 192 90 80 94 99 160 + 79 50 100000000 11 21 27 + 18 32 43 65 76 52 + 62 49 35 53 58 35 + 69 90 93 53 52 72 + 82 94 99 124 136 119 + 109 120 131 144 85 99 + 114 125 139 165 144 184 + 197 184 132 144 159 205 + 193 199 191 178 176 163 + 186 199 135 115 101 115 + 63 102 114 127 146 153 + 149 135 218 216 204 211 + 213 241 259 266 242 233 + 221 251 267 264 231 250 + 245 263 279 267 279 225 + 218 210 197 203 185 165 + 157 175 194 208 213 226 + 237 245 263 273 272 288 + 301 247 232 221 214 240 + 231 227 222 182 195 200 + 240 221 211 228 242 203 + 184 166 191 191 276 259 + 189 162 135 104 138 152 + 253 248 111 100 70 40 + 83 121 137 294 258 203 + 245 212 183 106 202 91 + 128 119 125 145 165 176 + 193 169 189 184 82 72 + 86 100 170 89 60 46 + 100000000 10 19 28 42 53 + 75 86 62 72 59 45 + 63 64 41 73 94 85 + 49 44 64 74 86 103 + 128 128 111 101 112 123 + 136 77 91 106 117 131 + 157 136 176 189 176 124 + 136 151 197 185 191 183 + 170 168 155 178 191 127 + 107 93 107 55 94 106 + 119 138 145 141 127 210 + 208 196 203 205 233 251 + 258 234 225 213 243 259 + 256 223 242 237 255 271 + 259 271 217 210 202 189 + 195 177 157 149 167 186 + 200 205 218 229 237 255 + 265 264 280 293 239 224 + 213 206 250 241 219 219 + 174 187 197 234 231 221 + 238 252 213 194 176 201 + 201 286 269 199 172 145 + 114 148 162 245 240 113 + 93 66 36 93 131 147 + 286 250 195 237 204 175 + 98 194 83 118 109 115 + 135 155 166 183 159 179 + 174 72 62 76 90 160 + 79 50 36 47 100000000 9 + 18 32 43 65 76 52 + 62 49 35 53 54 31 + 63 84 75 39 34 54 + 64 76 93 118 118 101 + 91 102 113 126 67 81 + 96 107 121 147 126 166 + 179 166 114 126 141 187 + 175 181 173 160 158 145 + 168 181 117 97 83 97 + 45 84 96 109 128 135 + 131 117 200 198 186 193 + 195 223 241 248 224 215 + 203 233 249 246 213 232 + 227 245 261 249 261 207 + 200 192 179 185 167 147 + 139 157 176 190 195 208 + 219 227 245 255 254 270 + 283 229 214 203 196 240 + 231 209 209 164 177 187 + 224 221 211 228 242 203 + 184 166 191 191 276 259 + 189 162 135 104 138 152 + 235 230 103 83 56 26 + 83 121 137 276 240 185 + 227 194 165 88 184 73 + 109 100 106 126 146 157 + 174 150 170 165 63 53 + 67 81 151 70 41 27 + 38 48 100000000 9 23 34 + 56 67 43 53 40 26 + 44 45 22 54 75 66 + 30 25 45 55 67 84 + 109 109 92 82 93 104 + 117 58 72 87 98 112 + 138 117 157 170 157 105 + 117 132 178 166 172 164 + 151 149 136 159 172 108 + 88 74 88 36 75 87 + 100 119 126 122 108 191 + 189 177 184 186 214 232 + 239 215 206 194 224 240 + 237 204 223 218 236 252 + 240 252 198 191 183 170 + 176 158 138 130 148 167 + 181 186 199 210 218 236 + 246 245 261 274 220 205 + 194 187 231 222 200 200 + 155 168 178 215 212 202 + 219 233 194 175 157 182 + 182 267 250 180 153 126 + 95 129 143 226 221 94 + 74 47 17 74 112 128 + 267 231 176 218 185 156 + 79 175 64 118 109 115 + 135 155 166 183 141 161 + 174 72 62 76 81 142 + 61 32 18 29 39 9 + 100000000 14 25 47 58 34 + 44 31 17 35 40 17 + 51 72 75 35 34 54 + 64 76 81 106 118 101 + 91 102 113 126 67 81 + 96 107 121 147 126 166 + 179 166 114 126 141 187 + 175 181 173 160 158 145 + 168 181 117 97 83 97 + 45 84 96 109 128 135 + 131 117 200 198 186 193 + 195 223 241 248 224 215 + 203 233 249 246 213 232 + 227 245 261 249 261 207 + 200 192 179 185 167 147 + 139 157 176 190 195 208 + 219 227 245 255 254 270 + 283 229 214 203 196 222 + 213 209 204 164 177 182 + 222 203 193 210 224 185 + 166 148 173 173 258 241 + 171 144 117 86 120 134 + 235 230 93 82 52 22 + 65 103 119 276 240 185 + 227 194 165 88 184 73 + 132 123 129 149 169 180 + 174 127 147 163 86 76 + 90 67 128 47 18 32 + 43 53 23 14 100000000 11 + 33 44 20 33 45 31 + 49 54 31 65 86 89 + 49 48 68 78 90 95 + 120 132 115 105 116 127 + 140 81 95 110 121 135 + 161 140 180 193 180 128 + 140 155 201 189 195 187 + 174 172 159 182 195 131 + 111 97 111 59 98 110 + 123 142 149 145 131 214 + 212 200 207 209 237 255 + 262 238 229 217 247 263 + 260 227 246 241 259 275 + 263 275 221 214 206 193 + 199 181 161 153 171 190 + 204 209 222 233 241 259 + 269 265 281 297 240 228 + 217 210 208 199 223 190 + 178 191 168 208 189 179 + 196 210 171 152 134 159 + 159 244 227 157 130 103 + 72 106 120 249 244 107 + 96 66 36 51 89 105 + 290 254 199 241 208 179 + 102 198 87 143 134 140 + 160 178 189 163 116 136 + 152 97 87 101 56 117 + 36 29 43 54 64 34 + 25 11 100000000 22 33 9 + 22 35 42 50 65 42 + 76 97 100 60 59 79 + 89 101 106 131 143 126 + 116 127 138 151 92 106 + 121 132 146 172 151 191 + 204 191 139 151 166 212 + 200 206 198 185 183 170 + 193 206 142 122 108 122 + 70 109 121 134 153 160 + 156 142 225 223 211 218 + 220 248 266 273 249 240 + 228 258 274 271 238 257 + 252 270 286 267 279 225 + 225 217 204 210 192 172 + 164 182 194 215 213 226 + 237 245 263 261 254 270 + 287 229 232 221 214 197 + 188 212 179 189 202 157 + 197 178 168 185 199 160 + 141 123 148 148 233 216 + 146 119 92 61 95 109 + 260 255 118 107 77 47 + 40 78 94 294 265 203 + 252 219 190 113 207 98 + 166 157 151 171 156 167 + 141 94 114 130 132 122 + 136 34 95 14 28 42 + 53 63 69 60 60 49 + 100000000 11 40 53 66 77 + 81 98 77 109 130 135 + 95 94 114 124 136 139 + 164 178 161 151 162 173 + 186 127 141 156 167 181 + 207 186 226 239 226 174 + 186 201 247 235 241 233 + 220 218 205 228 241 177 + 157 143 157 105 144 156 + 169 188 188 179 177 248 + 258 246 253 255 283 289 + 296 272 263 251 281 275 + 288 239 258 253 271 287 + 245 257 203 226 240 227 + 233 215 195 187 205 172 + 214 191 204 215 223 241 + 239 232 248 265 207 210 + 199 192 175 166 190 157 + 176 184 135 175 156 146 + 163 177 138 119 101 126 + 126 211 194 124 97 70 + 39 73 87 295 278 151 + 140 112 82 18 56 72 + 272 266 181 253 242 225 + 148 185 133 155 146 140 + 160 145 156 130 83 103 + 119 128 125 139 89 84 + 74 67 81 92 102 72 + 63 49 38 60 100000000 29 + 42 55 69 70 87 80 + 98 119 131 98 97 117 + 127 136 128 153 178 161 + 151 162 173 186 130 144 + 159 170 184 207 186 226 + 239 226 177 189 204 247 + 238 241 236 223 221 208 + 231 244 180 160 146 156 + 108 140 159 172 184 177 + 168 180 237 249 249 256 + 258 286 278 285 261 252 + 240 270 264 277 228 247 + 242 260 276 234 246 192 + 215 229 216 222 204 184 + 176 194 161 203 180 193 + 204 212 230 228 221 237 + 254 196 199 188 181 164 + 155 179 146 165 173 124 + 164 145 135 152 166 127 + 108 90 115 115 200 183 + 113 86 59 28 62 76 + 298 267 140 129 115 85 + 78 45 61 261 255 170 + 242 231 228 151 174 136 + 152 143 149 169 174 185 + 159 112 132 148 106 96 + 110 65 113 45 38 52 + 63 73 43 34 20 9 + 31 29 100000000 13 26 40 + 41 58 51 69 90 102 + 69 68 88 98 107 99 + 124 149 132 122 133 144 + 157 101 115 130 141 155 + 178 157 197 210 197 148 + 160 175 218 209 212 207 + 194 192 179 202 215 151 + 131 117 131 79 118 130 + 143 162 169 165 151 234 + 232 220 227 229 257 275 + 282 258 249 237 267 283 + 280 247 266 261 279 295 + 263 275 221 234 226 213 + 219 201 181 173 191 190 + 224 209 222 233 241 259 + 257 250 266 283 225 228 + 217 210 193 184 208 175 + 194 202 153 193 174 164 + 181 195 156 137 119 144 + 144 229 212 142 115 88 + 57 91 105 269 264 111 + 100 86 56 49 74 90 + 290 274 199 261 228 199 + 122 203 107 162 153 159 + 179 187 198 172 125 145 + 161 116 106 120 78 126 + 58 51 62 73 83 53 + 44 33 22 44 42 13 + 100000000 13 27 28 45 61 + 56 77 89 79 78 98 + 106 94 86 111 136 119 + 109 120 131 144 111 125 + 140 147 161 165 144 184 + 197 184 158 170 185 205 + 219 199 217 204 202 189 + 212 225 161 141 127 141 + 89 128 140 153 172 179 + 175 161 244 242 230 237 + 239 267 285 292 268 259 + 247 277 293 290 257 276 + 271 289 305 276 288 234 + 244 236 223 229 211 191 + 183 201 203 234 222 235 + 246 254 272 270 263 279 + 296 238 241 230 223 206 + 197 221 188 207 215 166 + 206 187 177 194 208 169 + 150 132 157 157 242 225 + 155 128 101 70 104 118 + 279 274 98 87 96 66 + 62 87 103 303 284 212 + 271 238 209 132 216 117 + 149 140 146 166 186 197 + 185 138 158 174 103 93 + 107 78 139 58 43 49 + 60 70 40 31 25 22 + 44 55 26 13 100000000 14 + 15 32 48 43 64 76 + 66 65 85 93 81 73 + 98 123 106 96 107 118 + 131 98 112 127 134 148 + 152 131 171 184 171 145 + 157 172 192 206 186 204 + 191 189 176 199 212 148 + 128 114 128 76 115 127 + 140 159 166 162 148 231 + 229 217 224 226 254 272 + 279 255 246 234 264 280 + 277 244 263 258 276 292 + 280 292 238 231 223 210 + 216 198 178 170 188 207 + 221 226 239 250 258 276 + 283 276 292 309 251 245 + 234 227 219 210 234 201 + 195 208 179 219 200 190 + 207 221 182 163 145 170 + 170 255 238 168 141 114 + 83 117 131 266 261 85 + 74 83 53 62 100 116 + 307 271 216 258 225 196 + 119 215 104 135 126 132 + 152 172 183 185 138 158 + 174 89 79 93 78 139 + 58 29 35 46 56 26 + 17 11 22 44 55 31 + 27 14 100000000 18 35 34 + 46 67 79 52 51 71 + 81 84 76 101 126 109 + 99 110 121 134 84 98 + 113 124 138 155 134 174 + 187 174 131 143 158 195 + 192 189 190 177 175 162 + 185 198 134 114 100 114 + 62 101 113 126 145 152 + 148 134 217 215 203 210 + 212 240 258 265 241 232 + 220 250 266 263 230 249 + 244 262 278 266 278 224 + 217 209 196 202 184 164 + 156 174 193 207 212 225 + 236 244 262 272 271 287 + 300 246 231 220 213 219 + 210 226 201 181 194 179 + 219 200 190 207 221 182 + 163 145 170 170 255 238 + 168 141 114 83 117 131 + 252 247 88 77 69 39 + 62 100 116 293 257 202 + 244 211 182 105 201 90 + 164 155 161 181 201 212 + 200 153 173 189 118 108 + 122 93 154 73 58 64 + 75 85 55 46 40 37 + 59 70 41 28 15 29 + 100000000 17 40 28 49 61 + 58 80 88 78 66 58 + 83 108 91 81 92 103 + 116 113 127 127 119 133 + 137 116 156 169 156 145 + 157 172 177 202 171 203 + 191 189 176 199 212 163 + 143 129 143 91 130 142 + 155 174 181 177 163 239 + 229 217 224 226 253 271 + 278 257 248 241 266 295 + 279 259 278 273 291 307 + 295 307 253 246 238 225 + 231 213 193 185 203 222 + 236 241 254 265 273 291 + 298 291 307 324 266 260 + 249 242 234 225 249 216 + 210 223 194 234 215 205 + 222 236 197 178 160 185 + 185 270 253 183 156 129 + 98 132 146 265 263 70 + 59 75 45 77 115 131 + 322 286 231 273 240 196 + 134 230 119 154 145 151 + 171 191 202 217 170 190 + 206 108 98 112 110 171 + 90 72 58 69 79 49 + 40 54 54 76 87 58 + 45 32 46 17 100000000 23 + 11 32 44 41 70 71 + 61 49 41 66 91 74 + 64 75 86 99 103 117 + 110 102 116 120 99 139 + 152 139 128 140 155 160 + 185 154 186 174 172 159 + 182 195 153 133 119 133 + 81 120 132 145 164 171 + 167 153 222 212 200 207 + 209 236 254 261 240 231 + 224 249 285 262 249 268 + 263 281 297 285 297 243 + 236 228 215 221 203 183 + 175 193 212 226 231 244 + 255 263 281 291 290 306 + 319 265 250 239 232 251 + 242 245 233 200 213 211 + 251 232 222 239 253 214 + 195 177 202 202 287 270 + 200 173 146 115 149 163 + 248 246 53 42 58 28 + 94 132 148 312 276 221 + 263 230 179 124 220 109 + 131 122 128 148 168 179 + 196 158 178 187 85 75 + 89 98 159 78 49 35 + 46 56 26 17 31 42 + 64 75 51 61 48 34 + 40 23 100000000 34 55 67 + 18 47 67 77 72 64 + 89 114 97 87 98 109 + 122 80 94 109 120 134 + 143 122 162 175 162 127 + 139 154 183 188 177 186 + 173 171 158 181 194 130 + 110 96 110 58 97 109 + 122 141 148 144 130 213 + 211 199 206 208 236 254 + 261 237 228 216 246 262 + 259 226 245 240 258 274 + 262 274 220 213 205 192 + 198 180 160 152 170 189 + 203 208 221 232 240 258 + 268 267 283 296 242 227 + 216 209 239 230 222 221 + 177 190 199 237 220 210 + 227 241 202 183 165 190 + 190 275 258 188 161 134 + 103 137 151 248 243 76 + 65 35 5 82 120 136 + 289 253 198 240 207 178 + 101 197 86 152 143 149 + 169 189 200 217 181 201 + 208 113 103 117 121 182 + 101 83 69 80 90 60 + 51 65 65 87 98 69 + 56 43 57 28 11 34 + 100000000 21 33 46 75 60 + 50 38 30 55 80 63 + 53 64 75 88 101 115 + 99 91 105 109 88 128 + 141 128 117 129 144 149 + 174 143 175 163 161 148 + 171 184 151 131 117 131 + 86 125 130 143 162 169 + 165 151 211 201 189 196 + 198 225 243 250 229 220 + 213 238 283 251 247 266 + 261 279 295 283 295 241 + 234 226 213 219 201 181 + 173 191 210 224 229 242 + 253 261 279 289 288 304 + 317 263 248 237 230 262 + 253 243 243 198 211 221 + 258 243 233 250 264 225 + 206 188 213 213 298 281 + 211 184 157 126 160 174 + 237 235 42 31 48 39 + 105 143 159 310 274 219 + 261 222 168 122 218 107 + 131 122 128 148 168 179 + 196 184 204 187 92 82 + 96 110 203 122 104 90 + 100 88 79 72 86 86 + 108 119 90 77 64 78 + 49 32 55 21 100000000 12 + 25 54 39 29 17 23 + 48 59 42 32 43 54 + 67 80 94 78 70 84 + 88 67 107 120 107 96 + 108 123 128 153 122 154 + 142 140 127 150 163 130 + 110 96 110 65 104 109 + 122 141 148 144 130 190 + 180 168 175 177 204 222 + 229 208 199 192 217 262 + 230 226 245 240 258 274 + 262 274 220 213 205 192 + 198 180 160 152 170 189 + 203 208 221 232 240 258 + 268 267 283 296 242 227 + 216 209 271 262 222 222 + 177 190 200 237 259 254 + 249 263 246 216 209 234 + 234 307 290 232 205 178 + 147 181 195 216 214 30 + 10 27 60 126 164 180 + 289 253 198 240 201 147 + 101 197 86 126 117 123 + 143 163 174 191 179 199 + 182 80 70 84 98 204 + 123 105 91 88 76 67 + 73 87 87 109 120 91 + 78 65 79 50 33 56 + 22 12 100000000 13 42 51 + 41 29 35 60 71 54 + 44 55 66 79 75 89 + 90 82 96 100 79 119 + 132 119 108 120 135 140 + 165 134 166 154 152 139 + 162 175 125 105 91 105 + 53 92 104 117 136 143 + 139 125 202 192 180 187 + 189 216 234 241 220 211 + 204 229 257 242 221 240 + 235 253 269 257 269 215 + 208 200 187 193 175 155 + 147 165 184 198 203 216 + 227 235 253 263 262 278 + 291 237 222 211 204 266 + 257 217 217 172 185 195 + 232 254 255 244 258 247 + 211 210 235 235 302 285 + 233 206 179 148 182 196 + 228 226 42 22 15 61 + 127 165 181 284 248 193 + 235 202 159 96 192 81 + 113 104 110 130 150 161 + 178 166 186 169 67 57 + 71 85 192 111 93 79 + 75 63 54 61 75 75 + 97 108 79 66 53 67 + 38 21 44 24 45 57 + 100000000 29 49 59 62 54 + 79 104 87 77 88 99 + 112 62 76 91 102 116 + 133 112 152 165 152 109 + 121 136 173 170 167 168 + 155 153 140 163 176 112 + 92 78 92 40 79 91 + 104 123 130 126 112 195 + 193 181 188 190 218 236 + 243 219 210 198 228 244 + 241 208 227 222 240 256 + 244 256 202 195 187 174 + 180 162 142 134 152 171 + 185 190 203 214 222 240 + 250 249 265 278 224 209 + 198 191 253 244 204 204 + 159 172 182 219 241 243 + 231 245 235 198 197 222 + 223 289 272 221 194 167 + 136 170 184 230 225 66 + 55 17 49 115 153 169 + 271 235 180 222 189 160 + 83 179 68 84 75 81 + 101 121 132 149 137 157 + 140 38 28 42 56 176 + 95 66 52 46 34 25 + 34 48 59 81 92 68 + 78 65 51 69 70 47 + 63 53 41 54 100000000 20 + 30 42 76 101 84 67 + 57 68 79 92 33 47 + 62 73 87 113 92 132 + 145 132 80 92 107 153 + 141 147 139 126 124 111 + 134 147 83 63 49 63 + 11 50 62 75 94 101 + 97 83 166 164 152 159 + 161 189 207 214 190 181 + 169 199 215 212 179 198 + 193 211 227 215 227 173 + 166 158 145 151 133 113 + 105 123 142 156 161 174 + 185 193 211 221 220 236 + 249 195 180 169 162 224 + 215 175 175 130 143 153 + 190 212 222 202 216 216 + 169 168 193 204 260 243 + 205 178 151 120 154 168 + 201 196 69 49 56 42 + 99 137 153 242 206 151 + 193 160 131 54 150 39 + 104 95 101 121 141 152 + 169 157 177 160 58 48 + 62 76 196 115 86 72 + 66 54 45 54 68 79 + 101 112 88 98 85 71 + 71 54 67 43 33 21 + 34 20 100000000 10 22 56 + 81 64 47 37 48 59 + 72 53 67 82 75 89 + 93 72 112 125 112 100 + 112 127 133 158 127 159 + 146 144 131 154 167 103 + 83 69 83 31 70 82 + 95 114 121 117 103 186 + 184 172 179 181 209 227 + 234 210 201 189 219 235 + 232 199 218 213 231 247 + 235 247 193 186 178 165 + 171 153 133 125 143 162 + 176 181 194 205 213 231 + 241 240 256 269 215 200 + 189 182 244 235 195 195 + 150 163 173 210 232 242 + 222 236 236 189 188 213 + 224 280 263 225 198 171 + 140 174 188 221 216 49 + 29 36 62 119 157 173 + 262 226 171 213 180 151 + 74 170 59 114 105 111 + 131 151 162 179 167 187 + 170 68 58 72 86 206 + 125 96 82 76 64 55 + 64 78 89 111 122 98 + 106 93 81 78 61 77 + 50 29 31 44 30 10 + 100000000 12 51 76 54 37 + 27 38 49 62 63 77 + 73 65 79 83 62 102 + 115 102 91 103 118 123 + 148 117 149 137 135 122 + 145 158 113 93 79 93 + 41 80 92 105 124 131 + 127 113 185 175 163 170 + 172 199 217 224 203 194 + 187 212 245 225 209 228 + 223 241 257 245 257 203 + 196 188 175 181 163 143 + 135 153 172 186 191 204 + 215 223 241 251 250 266 + 279 225 210 199 192 254 + 245 205 205 160 173 183 + 220 242 252 232 246 246 + 199 198 223 234 290 273 + 235 208 181 150 184 198 + 211 209 39 19 46 72 + 129 167 183 272 236 181 + 223 190 142 84 180 69 + 114 105 111 131 151 162 + 179 167 187 170 80 70 + 84 98 207 137 108 94 + 88 76 67 76 90 101 + 123 134 107 94 81 93 + 66 49 72 38 17 29 + 42 42 22 12 100000000 39 + 64 42 25 15 26 37 + 50 63 77 61 53 67 + 71 50 90 103 90 79 + 91 106 111 136 105 137 + 125 123 110 133 146 113 + 93 79 93 53 92 92 + 105 124 131 127 113 173 + 163 151 158 160 187 205 + 212 191 182 175 200 245 + 213 209 228 223 241 257 + 245 257 203 196 188 175 + 181 163 143 135 153 172 + 186 191 204 215 223 241 + 251 250 266 279 225 210 + 199 192 254 245 205 205 + 160 173 183 220 242 252 + 232 246 246 199 198 223 + 234 290 273 240 220 193 + 162 196 203 199 197 27 + 7 44 77 141 179 195 + 272 236 181 223 184 130 + 84 180 69 153 144 150 + 170 190 201 218 206 226 + 209 115 105 119 133 212 + 131 113 99 110 111 90 + 81 95 95 117 128 99 + 86 73 87 58 41 64 + 30 23 35 48 77 61 + 51 39 100000000 25 81 64 + 54 65 76 89 102 116 + 100 92 94 85 64 104 + 117 104 113 125 140 125 + 150 119 151 159 157 144 + 167 180 152 132 118 132 + 88 127 131 144 163 170 + 166 152 207 197 185 192 + 194 201 219 226 225 216 + 209 234 282 247 248 265 + 262 280 296 284 296 242 + 235 227 214 220 202 182 + 174 192 211 225 230 243 + 254 262 280 290 289 305 + 318 264 249 238 231 292 + 283 244 244 199 212 222 + 259 273 263 271 285 255 + 236 218 243 243 328 311 + 241 214 187 156 190 204 + 213 231 12 32 50 69 + 135 173 189 311 275 220 + 262 218 164 123 219 108 + 133 124 130 150 170 181 + 198 186 206 189 129 119 + 133 147 226 156 138 124 + 135 125 115 106 120 120 + 142 153 124 111 98 112 + 83 66 89 55 48 60 + 73 91 71 61 49 25 + 100000000 61 44 34 45 56 + 69 82 96 80 72 69 + 60 39 79 92 79 88 + 100 115 100 125 94 126 + 134 132 119 142 155 132 + 112 98 112 102 141 111 + 124 143 150 146 132 182 + 172 160 167 169 176 194 + 201 200 191 184 209 257 + 222 228 240 242 260 276 + 264 276 222 215 207 194 + 200 182 162 154 172 191 + 205 210 223 234 242 260 + 270 269 285 298 244 229 + 218 211 273 264 224 224 + 179 192 202 239 261 271 + 251 265 265 218 217 242 + 253 309 292 259 239 212 + 181 215 222 188 206 37 + 56 75 94 160 198 214 + 291 255 200 242 193 139 + 103 199 88 129 120 126 + 146 166 177 194 182 202 + 185 125 115 129 143 222 + 182 153 139 133 121 112 + 121 135 146 168 179 152 + 139 126 138 111 94 117 + 83 62 74 87 87 67 + 57 45 72 47 100000000 20 + 30 41 52 65 78 84 + 76 68 38 29 8 48 + 61 48 57 69 84 69 + 94 63 95 103 101 88 + 111 124 128 108 94 108 + 98 137 107 120 139 146 + 142 128 151 141 129 136 + 138 145 163 170 169 160 + 153 178 226 191 201 209 + 215 233 246 247 259 218 + 204 196 183 171 178 158 + 150 168 187 201 206 219 + 230 238 256 266 265 281 + 268 240 225 214 207 269 + 260 220 220 175 188 198 + 235 257 267 247 261 261 + 214 213 238 249 305 288 + 255 265 238 207 233 218 + 157 175 72 52 89 122 + 186 224 240 274 228 196 + 215 162 108 99 195 84 + 109 100 106 126 146 157 + 174 162 182 165 105 95 + 109 123 202 162 133 119 + 113 101 92 101 115 126 + 148 159 132 119 106 118 + 91 74 97 63 42 54 + 67 67 47 37 25 64 + 84 37 100000000 10 21 32 + 45 58 72 56 48 62 + 66 45 85 98 85 74 + 86 101 106 131 100 132 + 120 118 105 128 141 108 + 88 74 88 78 117 87 + 100 119 126 122 108 168 + 158 146 153 155 182 200 + 207 186 177 170 195 240 + 208 204 223 218 236 252 + 240 252 198 191 183 170 + 176 158 138 130 148 167 + 181 186 199 210 218 236 + 246 245 261 274 220 205 + 194 187 249 240 200 200 + 155 168 178 215 237 247 + 227 241 241 194 193 218 + 229 285 268 235 245 218 + 187 213 198 194 192 52 + 32 69 102 166 204 220 + 267 231 176 218 179 125 + 79 175 64 99 90 96 + 116 136 147 164 152 172 + 155 95 85 99 113 192 + 152 123 109 103 91 82 + 91 105 116 138 149 122 + 109 96 108 81 64 87 + 53 32 44 57 57 37 + 27 15 54 74 27 10 + 100000000 11 22 35 48 62 + 46 38 52 56 35 75 + 88 75 64 76 91 96 + 121 90 122 110 108 95 + 118 131 98 78 64 78 + 68 107 77 90 109 116 + 112 98 158 148 136 143 + 145 172 190 197 176 167 + 160 185 230 198 194 213 + 208 226 242 230 242 188 + 181 173 160 166 148 128 + 120 138 157 171 176 189 + 200 208 226 236 235 251 + 264 210 195 184 177 239 + 230 190 190 145 158 168 + 205 227 237 217 231 231 + 184 183 208 219 275 258 + 225 235 208 177 203 188 + 184 182 42 22 59 92 + 156 194 210 257 221 166 + 208 169 115 69 165 54 + 88 79 85 105 125 136 + 153 141 161 144 95 85 + 99 113 181 152 123 109 + 103 91 82 91 105 116 + 138 149 125 133 120 108 + 105 88 104 77 56 58 + 71 57 37 27 39 78 + 102 55 64 54 100000000 11 + 24 37 51 35 27 41 + 84 63 103 116 103 53 + 65 80 124 114 118 112 + 99 97 84 107 120 87 + 67 53 67 68 107 66 + 79 98 105 101 87 147 + 137 125 132 134 162 180 + 187 165 156 149 174 219 + 187 183 202 197 215 231 + 219 231 177 170 162 149 + 155 137 117 109 127 146 + 160 165 178 189 197 215 + 225 224 240 253 199 184 + 173 166 228 219 179 179 + 134 147 157 194 216 226 + 206 220 220 173 172 197 + 208 264 247 214 228 201 + 177 192 177 174 171 66 + 46 73 99 156 194 210 + 246 210 155 197 158 104 + 58 154 43 77 68 74 + 94 114 125 142 130 150 + 133 84 74 88 102 170 + 141 112 98 92 80 71 + 80 94 105 127 138 114 + 122 109 97 94 77 93 + 66 45 47 60 46 26 + 16 28 67 91 44 53 + 43 51 100000000 13 26 40 + 24 16 30 73 52 92 + 105 92 42 54 69 113 + 103 107 101 88 86 73 + 96 109 76 56 42 56 + 57 96 55 68 87 94 + 90 76 136 126 114 121 + 123 151 169 176 154 145 + 138 163 208 176 172 191 + 186 204 220 208 220 166 + 159 151 138 144 126 106 + 98 116 135 149 154 167 + 178 186 204 214 213 229 + 242 188 173 162 155 217 + 208 168 168 123 136 146 + 183 205 215 195 209 209 + 162 161 186 197 253 236 + 203 217 190 166 181 166 + 163 160 55 35 62 88 + 145 183 199 235 199 144 + 186 147 93 47 143 32 + 64 55 61 81 101 112 + 129 117 137 120 84 74 + 88 102 157 141 112 98 + 92 80 71 80 94 105 + 127 138 114 124 111 97 + 111 94 93 83 73 61 + 74 46 40 50 62 96 + 97 50 70 77 57 68 + 100000000 13 27 11 22 36 + 79 58 98 111 98 29 + 41 56 119 90 109 88 + 75 73 60 83 96 63 + 43 29 43 57 96 42 + 55 74 81 77 63 123 + 113 101 108 110 138 156 + 163 141 132 125 150 195 + 163 159 178 173 191 207 + 195 207 153 146 138 125 + 131 113 93 85 103 122 + 136 141 154 165 173 191 + 201 200 216 229 175 160 + 149 142 204 195 155 155 + 110 123 133 170 192 202 + 182 196 196 149 148 173 + 184 240 223 190 204 177 + 166 168 153 150 147 89 + 69 76 88 145 183 199 + 222 186 131 173 134 80 + 34 130 19 51 42 48 + 68 88 99 116 104 124 + 107 71 61 75 89 144 + 128 99 85 79 67 58 + 67 81 92 114 125 101 + 111 98 84 98 81 80 + 70 60 48 61 33 27 + 37 49 83 108 68 74 + 64 75 86 99 100000000 14 + 29 40 54 97 76 116 + 129 116 47 59 74 137 + 108 127 106 93 91 78 + 101 114 50 30 16 30 + 44 83 29 42 61 68 + 64 50 133 131 119 126 + 128 156 174 181 157 148 + 136 166 182 179 146 165 + 160 178 194 182 194 140 + 133 125 112 118 100 80 + 72 90 109 123 128 141 + 152 160 178 188 187 203 + 216 162 147 136 129 191 + 182 142 142 97 110 120 + 157 179 189 169 183 183 + 136 135 160 171 227 210 + 177 191 164 153 155 140 + 168 163 76 56 63 75 + 132 170 186 209 173 118 + 160 127 98 21 117 6 + 65 56 62 82 102 113 + 130 118 138 121 85 75 + 89 103 158 142 113 99 + 93 81 72 81 95 106 + 128 139 115 125 112 98 + 112 95 94 84 74 62 + 75 47 41 51 63 97 + 101 54 74 78 61 72 + 85 14 100000000 15 26 40 + 83 62 102 115 102 33 + 45 60 123 94 113 92 + 79 77 64 87 100 64 + 44 30 44 58 97 43 + 56 75 82 78 64 127 + 117 105 112 114 142 160 + 167 145 136 129 154 196 + 167 160 179 174 192 208 + 196 208 154 147 139 126 + 132 114 94 86 104 123 + 137 142 155 166 174 192 + 202 201 217 230 176 161 + 150 143 205 196 156 156 + 111 124 134 171 193 203 + 183 197 197 150 149 174 + 185 241 224 191 205 178 + 167 169 154 154 151 90 + 70 77 89 146 184 200 + 223 187 132 174 138 84 + 35 131 20 110 101 107 + 127 147 158 175 163 183 + 166 130 120 134 148 203 + 187 158 144 138 126 117 + 126 140 151 173 184 160 + 170 157 143 150 133 139 + 122 101 104 117 92 83 + 73 84 111 86 39 59 + 69 46 57 70 59 45 + 100000000 11 25 68 47 87 + 100 87 18 30 45 108 + 79 98 77 64 62 49 + 72 85 109 89 75 89 + 103 142 88 101 120 127 + 123 109 112 102 90 97 + 99 127 145 152 130 121 + 114 139 198 152 162 181 + 176 194 210 208 220 193 + 165 157 144 132 159 139 + 131 149 168 182 187 200 + 211 219 237 235 242 249 + 232 221 206 195 188 250 + 241 201 201 156 169 179 + 216 238 248 228 242 242 + 195 194 219 230 286 269 + 236 250 223 212 214 199 + 139 136 111 91 119 134 + 191 229 245 235 189 177 + 176 123 69 80 176 65 + 123 114 120 140 160 171 + 188 176 196 179 130 120 + 134 148 216 187 158 144 + 138 126 117 126 140 151 + 173 184 160 167 154 143 + 139 122 139 111 90 93 + 106 92 72 62 73 100 + 75 28 48 58 35 46 + 59 72 86 70 100000000 14 + 57 36 76 89 76 85 + 97 112 97 122 91 123 + 131 129 116 139 152 122 + 102 88 102 103 142 101 + 114 133 140 136 122 179 + 169 157 164 166 173 191 + 198 197 188 181 206 254 + 219 218 237 232 250 266 + 254 266 212 205 197 184 + 190 172 152 144 162 181 + 195 200 213 224 232 250 + 260 259 275 288 234 219 + 208 201 263 254 214 214 + 169 182 192 229 251 261 + 241 255 255 208 207 232 + 243 299 282 249 263 236 + 212 227 212 185 203 100 + 80 108 134 191 229 245 + 281 245 190 232 190 136 + 93 189 78 109 100 106 + 126 146 157 174 162 182 + 165 116 106 120 134 202 + 173 144 130 124 112 103 + 112 126 137 159 170 146 + 153 140 129 125 108 125 + 97 76 79 92 78 58 + 48 59 86 61 14 34 + 44 21 32 45 58 72 + 56 48 100000000 43 22 62 + 75 62 71 83 98 83 + 108 77 109 117 115 102 + 125 138 108 88 74 88 + 89 128 87 100 119 126 + 122 108 165 155 143 150 + 152 159 177 184 183 174 + 167 192 240 205 204 223 + 218 236 252 240 252 198 + 191 183 170 176 158 138 + 130 148 167 181 186 199 + 210 218 236 246 245 261 + 274 220 205 194 187 249 + 240 200 200 155 168 178 + 215 237 247 227 241 241 + 194 193 218 229 285 268 + 235 249 222 198 213 198 + 171 189 86 66 94 120 + 177 215 231 267 231 176 + 218 176 122 79 175 64 + 118 109 115 135 155 166 + 183 171 191 174 125 115 + 129 143 211 182 153 139 + 133 121 112 121 135 146 + 168 179 155 162 149 138 + 134 117 134 106 85 88 + 101 87 67 57 68 95 + 70 23 43 53 30 41 + 54 67 55 65 57 9 + 100000000 31 71 32 19 28 + 40 55 40 65 60 87 + 74 72 59 82 95 117 + 97 83 97 98 137 96 + 109 128 135 131 117 122 + 112 100 107 109 137 155 + 162 140 131 124 149 208 + 162 172 191 186 204 220 + 218 230 203 175 167 154 + 142 167 147 139 157 176 + 190 195 208 219 227 245 + 245 252 259 242 229 214 + 203 196 258 249 209 209 + 164 177 187 224 246 256 + 236 250 250 203 202 227 + 238 294 277 244 258 231 + 207 222 207 149 146 95 + 75 103 129 186 224 240 + 245 199 185 186 133 79 + 88 184 73 139 130 136 + 156 176 187 204 192 212 + 195 146 136 150 164 232 + 195 174 160 154 142 133 + 142 156 159 181 192 163 + 150 137 151 122 105 128 + 94 87 99 112 108 88 + 78 88 64 39 44 64 + 73 51 62 75 88 76 + 86 78 30 21 100000000 40 + 53 40 49 61 76 61 + 86 55 87 95 93 80 + 103 116 138 118 104 118 + 119 158 117 130 149 156 + 152 138 143 133 121 128 + 130 137 155 162 161 152 + 145 170 218 183 193 201 + 207 225 238 239 251 224 + 196 188 175 163 188 168 + 160 178 197 211 216 229 + 240 248 266 266 273 277 + 260 250 235 224 217 279 + 270 230 230 185 198 208 + 245 267 277 257 271 271 + 224 223 248 259 315 298 + 265 278 251 220 243 228 + 149 167 76 95 114 133 + 199 237 253 266 220 206 + 207 154 100 109 205 94 + 179 170 176 196 216 227 + 244 232 252 235 186 176 + 190 204 272 235 214 200 + 194 182 173 182 196 199 + 221 232 203 190 177 191 + 162 145 168 134 127 139 + 152 148 128 118 128 104 + 79 84 104 113 91 102 + 115 128 116 126 118 70 + 61 40 100000000 22 80 89 + 101 46 30 55 15 47 + 65 70 57 80 93 129 + 158 144 158 159 198 157 + 170 189 196 192 178 120 + 110 98 105 107 97 115 + 122 138 129 122 147 178 + 160 170 161 184 202 198 + 216 228 201 173 165 152 + 140 228 208 200 218 237 + 212 256 269 245 253 271 + 243 250 237 220 275 275 + 264 257 319 310 270 270 + 225 238 248 285 307 317 + 297 311 311 264 263 288 + 299 355 338 305 318 291 + 260 283 268 109 128 116 + 135 154 173 239 277 293 + 227 197 246 184 131 77 + 149 245 134 205 196 202 + 222 242 253 270 258 278 + 261 225 215 229 243 298 + 278 253 239 233 221 212 + 221 235 242 264 275 246 + 233 220 234 205 188 211 + 177 170 182 195 187 171 + 161 171 147 122 127 147 + 156 134 145 158 154 140 + 155 161 113 104 83 43 + 100000000 123 132 125 24 8 + 33 28 56 43 48 35 + 58 71 107 184 170 184 + 198 237 183 196 215 222 + 218 204 98 88 76 83 + 85 106 124 131 116 107 + 100 125 184 138 148 167 + 162 180 196 194 206 179 + 151 143 130 118 213 226 + 226 244 215 190 234 247 + 223 231 249 221 228 235 + 218 253 253 242 235 297 + 288 248 261 251 264 274 + 263 285 295 275 289 298 + 290 289 314 325 333 316 + 317 344 318 303 309 294 + 118 122 159 178 197 216 + 282 320 336 221 175 224 + 162 109 55 175 271 160 + 101 92 98 118 138 149 + 166 154 174 157 121 111 + 125 139 194 178 149 135 + 129 117 108 117 131 142 + 164 175 151 161 148 134 + 148 131 130 120 110 98 + 111 83 77 87 99 133 + 135 90 110 114 97 108 + 121 50 36 51 62 76 + 117 96 56 13 100000000 9 + 21 36 21 46 41 68 + 55 53 40 63 76 100 + 80 66 80 94 133 79 + 92 111 118 114 100 103 + 93 81 88 90 118 136 + 143 121 112 105 130 189 + 143 153 172 167 185 201 + 199 211 184 156 148 135 + 123 150 130 122 140 159 + 173 178 191 202 210 228 + 226 233 240 223 212 197 + 186 179 241 232 192 192 + 147 160 170 207 229 239 + 219 233 233 186 185 210 + 221 277 260 227 241 214 + 203 205 190 130 127 126 + 106 113 125 182 220 236 + 226 180 168 167 114 60 + 71 167 56 92 83 89 + 109 129 140 157 145 165 + 148 112 102 116 130 185 + 169 140 126 120 108 99 + 108 122 133 155 166 142 + 152 139 125 139 122 121 + 111 101 89 102 74 68 + 78 90 124 128 81 101 + 105 88 99 112 41 27 + 42 53 67 110 89 95 + 117 129 100000000 12 27 125 + 61 80 59 46 44 31 + 54 67 91 71 57 71 + 85 124 70 83 102 109 + 105 91 94 84 72 79 + 81 109 127 134 112 103 + 96 121 180 134 144 163 + 158 176 192 190 202 175 + 147 139 126 114 141 121 + 113 131 150 164 169 182 + 193 201 219 217 224 231 + 214 203 188 177 170 232 + 223 183 183 138 151 161 + 198 220 230 210 224 224 + 177 176 201 212 268 251 + 218 232 205 194 196 181 + 121 118 117 97 104 116 + 173 211 227 217 171 159 + 158 105 51 62 158 47 + 80 71 77 97 117 128 + 145 133 153 136 100 90 + 104 118 173 157 128 114 + 108 96 87 96 110 121 + 143 154 130 140 127 113 + 127 110 109 99 89 77 + 90 62 56 66 78 112 + 116 69 89 93 76 87 + 100 29 15 30 41 55 + 98 77 83 105 117 48 + 100000000 15 113 49 68 47 + 34 32 19 42 55 79 + 59 45 59 73 112 58 + 71 90 97 93 79 82 + 72 60 67 69 97 115 + 122 100 91 84 109 168 + 122 132 151 146 164 180 + 178 190 163 135 127 114 + 102 129 109 101 119 138 + 152 157 170 181 189 207 + 205 212 219 202 191 176 + 165 158 220 211 171 171 + 126 139 149 186 208 218 + 198 212 212 165 164 189 + 200 256 239 206 220 193 + 182 184 169 109 106 105 + 85 92 104 161 199 215 + 205 159 147 146 93 39 + 50 146 35 181 172 178 + 198 218 229 246 234 254 + 237 201 191 205 219 274 + 258 229 215 209 197 188 + 197 211 222 244 255 231 + 241 228 214 228 211 210 + 200 190 178 191 163 157 + 167 179 172 147 152 172 + 181 159 170 183 130 116 + 131 142 138 129 108 68 + 90 148 149 101 100000000 98 + 34 53 32 19 24 11 + 34 47 83 160 146 160 + 174 213 159 172 191 198 + 194 180 74 64 52 59 + 61 82 100 107 92 83 + 76 101 160 114 124 143 + 138 156 172 170 182 155 + 127 119 106 94 189 202 + 202 220 191 166 210 223 + 199 207 225 197 204 211 + 194 229 229 218 211 273 + 264 224 237 227 240 250 + 239 261 271 251 265 274 + 266 265 290 301 309 292 + 293 320 294 283 285 270 + 94 98 184 186 193 205 + 262 300 316 197 151 200 + 138 85 31 151 247 136 + 197 188 194 214 234 245 + 262 250 270 253 217 207 + 221 235 290 274 245 231 + 225 213 204 213 227 238 + 260 271 247 249 236 230 + 221 204 226 193 186 194 + 207 179 173 177 187 163 + 138 143 163 172 150 161 + 174 146 132 147 158 129 + 120 99 59 81 139 148 + 117 16 100000000 25 44 48 + 35 40 27 50 63 99 + 176 162 176 190 229 175 + 188 207 214 210 196 90 + 80 68 75 77 98 116 + 123 108 99 92 117 176 + 130 140 159 154 172 188 + 186 198 171 143 135 122 + 110 205 218 218 236 207 + 182 226 239 215 223 241 + 213 220 227 210 245 245 + 234 227 289 280 240 253 + 243 256 266 255 277 287 + 267 281 290 282 281 306 + 317 325 308 309 336 310 + 299 301 286 110 114 175 + 194 209 221 278 316 332 + 213 167 216 154 101 47 + 167 263 152 213 204 210 + 230 250 261 278 266 286 + 269 220 210 224 238 306 + 269 248 234 228 216 207 + 216 230 233 255 266 237 + 224 211 225 196 179 202 + 168 161 173 186 182 162 + 152 162 138 113 118 138 + 147 125 136 149 162 150 + 160 152 104 95 74 34 + 56 114 123 135 80 64 + 100000000 19 51 99 104 91 + 114 127 163 192 178 192 + 193 232 191 204 223 230 + 226 212 154 144 132 139 + 125 101 119 126 144 147 + 156 161 182 174 184 165 + 198 216 202 230 242 215 + 195 187 186 174 249 242 + 234 252 251 226 270 283 + 259 267 285 254 257 241 + 224 282 289 278 271 332 + 323 284 297 259 272 282 + 299 321 331 311 325 334 + 298 297 322 333 368 351 + 339 352 325 294 317 302 + 113 132 150 169 188 207 + 273 311 327 231 211 260 + 198 165 111 183 279 168 + 194 185 191 211 231 242 + 259 247 267 250 201 191 + 205 219 287 250 229 215 + 209 197 188 197 211 214 + 236 247 218 205 192 206 + 177 160 183 149 142 154 + 167 163 143 133 143 119 + 94 99 119 128 106 117 + 130 143 131 141 133 85 + 76 55 15 37 95 104 + 116 61 45 70 100000000 32 + 80 85 72 95 108 144 + 173 159 173 174 213 172 + 185 204 211 207 193 135 + 125 113 120 106 82 100 + 107 125 128 137 142 163 + 155 165 146 179 197 183 + 211 223 196 176 168 167 + 155 230 223 215 233 232 + 207 251 264 240 248 266 + 235 238 222 205 263 270 + 259 252 313 304 265 278 + 240 253 263 280 302 312 + 292 306 315 279 278 303 + 314 349 332 320 333 306 + 275 298 283 94 113 131 + 150 169 188 254 292 308 + 212 192 241 179 146 92 + 164 260 149 217 208 214 + 234 254 265 282 270 290 + 273 233 223 237 251 310 + 282 261 247 241 229 220 + 229 243 246 268 279 250 + 237 224 238 209 192 215 + 181 174 186 199 195 175 + 165 175 151 126 131 151 + 160 138 149 162 166 152 + 167 165 117 108 87 47 + 69 127 136 137 93 77 + 102 32 100000000 112 113 104 + 103 88 119 196 182 196 + 206 245 195 208 227 234 + 230 216 104 100 88 89 + 74 50 68 75 93 96 + 106 110 131 123 133 114 + 147 165 151 179 191 164 + 144 136 136 124 198 211 + 238 256 200 175 219 232 + 208 216 234 203 206 190 + 173 231 238 227 220 281 + 272 233 246 263 276 273 + 248 270 280 260 274 283 + 289 301 326 337 317 300 + 302 329 330 307 321 306 + 62 81 163 182 201 220 + 286 324 340 180 160 209 + 147 115 120 187 283 172 + 228 219 225 245 265 276 + 293 281 301 284 235 225 + 239 253 321 284 263 249 + 243 231 222 231 245 248 + 270 281 252 239 226 240 + 211 194 217 183 176 188 + 201 197 177 167 177 153 + 128 133 153 162 140 151 + 164 177 165 175 167 119 + 110 89 49 71 129 138 + 150 95 79 15 34 13 + 100000000 119 106 116 101 132 + 207 193 207 208 247 206 + 219 238 245 241 227 117 + 113 101 102 87 63 81 + 88 106 109 119 123 144 + 136 146 127 160 178 164 + 192 204 177 157 149 149 + 137 211 224 249 267 213 + 188 232 245 221 229 247 + 216 219 203 186 244 251 + 240 233 294 285 246 259 + 274 287 286 261 283 293 + 273 287 296 302 312 337 + 348 330 313 315 342 340 + 309 332 317 75 94 165 + 184 203 222 288 326 342 + 193 173 222 160 128 126 + 198 294 183 157 148 154 + 174 194 205 222 210 230 + 213 177 167 181 195 250 + 234 205 191 185 173 164 + 173 187 198 220 231 207 + 217 204 190 204 187 186 + 176 166 154 167 139 133 + 143 155 167 142 146 166 + 170 153 164 177 106 92 + 107 118 132 124 103 63 + 85 143 125 77 92 93 + 29 48 27 14 100000000 96 + 10 23 59 136 122 136 + 150 189 135 148 167 174 + 170 156 50 40 28 35 + 37 77 85 92 68 59 + 52 77 136 90 100 119 + 114 132 148 146 158 131 + 103 95 82 70 165 178 + 178 196 167 142 186 199 + 175 183 201 173 180 187 + 170 205 205 194 187 249 + 240 200 213 203 216 226 + 215 237 247 227 241 250 + 242 241 266 277 285 268 + 269 296 270 259 261 246 + 89 74 179 162 169 181 + 238 276 292 173 127 176 + 114 61 7 127 223 112 + 170 161 167 187 207 218 + 235 223 243 226 190 180 + 194 208 263 247 218 204 + 198 186 177 186 200 211 + 233 244 220 230 217 203 + 217 200 199 189 179 167 + 180 152 146 156 168 180 + 155 159 179 183 166 177 + 190 119 105 120 131 145 + 137 116 76 98 156 138 + 90 105 106 42 61 40 + 27 13 100000000 23 36 72 + 149 135 149 163 202 148 + 161 180 187 183 169 63 + 53 41 48 50 90 98 + 105 81 72 65 90 149 + 103 113 132 127 145 161 + 159 171 144 116 108 95 + 83 178 191 191 209 180 + 155 199 212 188 196 214 + 186 193 200 183 218 218 + 207 200 262 253 213 226 + 216 229 239 228 250 260 + 240 254 263 255 254 279 + 290 298 281 282 309 283 + 272 274 259 102 87 192 + 175 182 194 251 289 305 + 186 140 189 127 74 20 + 140 236 125 147 138 144 + 164 184 195 212 200 220 + 203 167 157 171 185 240 + 224 195 181 175 163 154 + 163 177 188 210 221 197 + 207 194 180 194 177 176 + 166 156 144 157 129 123 + 133 145 177 152 136 156 + 160 143 154 167 96 82 + 97 108 122 134 113 73 + 95 153 115 67 82 103 + 39 58 37 24 10 86 + 100000000 33 49 126 112 126 + 140 179 125 138 157 164 + 160 146 40 30 18 25 + 47 87 80 87 63 54 + 42 72 131 85 95 114 + 109 127 143 141 153 126 + 93 85 72 60 160 173 + 168 186 162 137 181 194 + 170 178 196 168 175 182 + 165 200 200 189 182 244 + 235 195 208 193 206 216 + 210 232 242 222 236 245 + 232 231 256 267 280 263 + 264 287 260 249 251 236 + 99 69 172 152 159 171 + 228 266 282 168 122 171 + 109 51 17 117 213 102 + 157 148 154 174 194 205 + 222 210 230 213 177 167 + 181 195 250 234 205 191 + 185 173 164 173 187 198 + 220 231 207 217 204 190 + 204 187 186 176 166 154 + 167 139 133 143 155 189 + 167 146 166 170 153 164 + 177 106 92 107 118 132 + 149 128 88 110 168 125 + 77 92 118 54 73 52 + 39 25 96 15 100000000 59 + 136 122 136 150 189 135 + 148 167 174 170 156 44 + 40 28 29 14 80 62 + 69 45 36 46 54 113 + 67 77 96 91 109 125 + 123 135 108 88 80 76 + 64 142 155 178 196 144 + 119 163 176 152 160 178 + 150 157 164 147 182 182 + 171 164 226 217 177 190 + 203 216 217 192 214 224 + 204 218 227 233 241 266 + 277 262 245 246 273 270 + 259 261 246 92 51 182 + 162 169 181 238 276 292 + 150 104 153 91 55 32 + 127 223 112 98 89 95 + 115 135 146 163 151 171 + 154 118 108 122 136 191 + 175 146 132 126 114 105 + 114 128 139 161 172 148 + 158 145 131 145 128 127 + 117 107 95 108 80 74 + 84 96 130 134 87 107 + 111 94 105 118 47 33 + 48 59 73 116 95 101 + 123 135 66 18 33 131 + 67 86 65 52 50 37 + 60 73 100000000 77 63 77 + 91 130 76 89 108 115 + 111 97 100 90 78 85 + 87 115 133 140 118 109 + 102 127 186 140 150 169 + 164 182 198 196 208 181 + 153 145 132 120 147 127 + 119 137 156 170 175 188 + 199 207 225 223 230 237 + 220 209 194 183 176 238 + 229 189 189 144 157 167 + 204 226 236 216 230 230 + 183 182 207 218 274 257 + 224 238 211 200 202 187 + 127 124 123 103 110 122 + 179 217 233 223 177 165 + 164 111 57 68 164 53 + 47 38 44 64 84 95 + 112 100 120 103 74 64 + 78 92 140 149 120 102 + 82 70 79 88 102 113 + 135 146 122 132 119 105 + 123 111 101 100 90 78 + 91 63 57 67 79 113 + 138 98 104 94 105 116 + 129 30 44 59 70 84 + 127 106 121 143 146 77 + 38 53 151 87 106 85 + 72 70 57 80 93 20 + 100000000 14 28 47 86 25 + 12 31 38 47 20 120 + 110 98 105 107 135 153 + 160 138 129 122 147 178 + 160 142 161 156 174 190 + 178 190 136 129 121 108 + 114 96 76 68 86 105 + 119 124 137 148 156 174 + 184 183 199 212 158 143 + 132 125 187 178 138 138 + 93 106 116 153 175 185 + 165 179 179 132 131 156 + 167 223 206 173 187 160 + 174 151 136 147 144 106 + 86 93 96 153 168 192 + 205 169 114 156 123 77 + 39 113 24 35 26 32 + 52 72 83 100 88 108 + 91 60 50 64 78 128 + 135 106 88 68 56 65 + 74 88 99 121 132 108 + 118 105 91 109 97 87 + 86 76 64 77 49 43 + 53 65 99 124 84 90 + 80 91 102 115 16 30 + 45 56 70 113 92 132 + 145 132 63 72 87 153 + 121 140 119 106 104 91 + 114 127 54 34 100000000 14 + 33 72 13 26 45 52 + 48 34 117 129 132 139 + 141 169 158 165 141 132 + 120 150 166 163 130 149 + 144 162 178 166 178 124 + 117 109 96 102 84 64 + 56 74 93 107 112 125 + 136 144 162 172 171 187 + 200 146 131 120 113 175 + 166 126 126 81 94 104 + 141 163 173 153 167 167 + 120 119 144 155 211 194 + 161 175 148 160 139 124 + 181 147 92 72 79 82 + 139 156 180 193 157 102 + 144 111 111 25 101 10 + 160 151 157 177 197 208 + 225 201 221 216 46 36 + 50 64 202 121 92 74 + 54 42 51 60 74 85 + 107 118 94 104 91 77 + 95 96 73 105 126 117 + 81 76 96 106 118 135 + 160 160 143 133 144 155 + 168 109 123 138 149 163 + 189 168 208 221 208 156 + 168 183 229 217 223 215 + 202 200 187 210 223 159 + 139 125 100000000 19 58 138 + 151 170 177 173 159 242 + 240 228 235 237 265 283 + 290 266 257 245 275 291 + 288 255 274 269 287 303 + 291 303 249 242 234 221 + 227 209 189 181 199 218 + 232 237 250 261 269 287 + 297 296 312 325 271 256 + 245 238 282 273 251 251 + 206 219 229 266 263 253 + 270 284 245 226 208 233 + 233 318 301 231 204 177 + 146 180 194 277 272 145 + 125 98 68 125 163 179 + 318 282 227 269 236 207 + 130 226 115 141 132 138 + 158 178 189 206 182 202 + 197 27 17 31 45 183 + 102 73 55 35 23 32 + 41 55 66 88 99 75 + 85 72 58 76 77 54 + 86 107 98 62 57 77 + 87 99 116 141 141 124 + 114 125 136 149 90 104 + 119 130 144 170 149 189 + 202 189 137 149 164 210 + 198 204 196 183 181 168 + 191 204 140 120 106 55 + 100000000 39 119 132 151 158 + 154 140 223 221 209 216 + 218 246 264 271 247 238 + 226 256 272 269 236 255 + 250 268 284 272 284 230 + 223 215 202 208 190 170 + 162 180 199 213 218 231 + 242 250 268 278 277 293 + 306 252 237 226 219 263 + 254 232 232 187 200 210 + 247 244 234 251 265 226 + 207 189 214 214 299 282 + 212 185 158 127 161 175 + 258 253 126 106 79 49 + 106 144 160 299 263 208 + 250 217 188 111 207 96 + 176 167 173 193 213 224 + 241 217 237 232 62 52 + 66 80 218 137 108 90 + 70 58 67 76 90 101 + 123 134 110 120 107 93 + 111 112 89 121 142 133 + 97 92 112 122 134 151 + 176 176 159 149 160 171 + 184 125 139 154 165 179 + 205 184 224 237 224 172 + 184 199 245 233 239 231 + 218 216 203 226 239 175 + 155 141 16 35 100000000 154 + 167 186 193 189 175 258 + 256 244 251 253 281 299 + 306 282 273 261 291 307 + 304 271 290 285 303 319 + 307 319 265 258 250 237 + 243 225 205 197 215 234 + 248 253 266 277 285 303 + 313 312 328 341 287 272 + 261 254 298 289 267 267 + 222 235 245 282 279 269 + 286 300 261 242 224 249 + 249 334 317 247 220 193 + 162 196 210 293 288 161 + 141 114 84 141 179 195 + 334 298 243 285 252 223 + 146 242 131 22 13 19 + 39 59 70 87 75 95 + 78 73 63 77 91 115 + 131 119 101 81 69 78 + 87 101 112 134 145 121 + 131 118 104 122 110 100 + 99 89 77 90 62 56 + 66 78 112 137 97 103 + 93 104 115 128 29 43 + 58 69 83 126 105 145 + 158 145 76 63 78 166 + 112 131 110 97 95 82 + 105 118 45 25 13 27 + 46 85 100000000 13 32 39 + 35 21 104 116 123 130 + 132 160 145 152 128 119 + 107 137 153 150 117 136 + 131 149 165 153 165 111 + 104 96 83 89 71 51 + 43 61 80 94 99 112 + 123 131 149 159 158 174 + 187 133 118 107 100 162 + 153 113 113 68 81 91 + 128 150 160 140 154 154 + 107 106 131 142 198 181 + 148 162 135 160 126 111 + 172 134 105 85 92 95 + 135 143 167 180 144 89 + 131 98 102 38 88 23 + 35 26 32 52 72 83 + 100 88 108 91 86 76 + 90 104 128 144 132 114 + 94 82 91 100 114 125 + 147 158 134 144 131 117 + 135 123 113 112 102 90 + 103 75 69 79 91 125 + 150 110 116 106 117 128 + 141 42 56 71 82 96 + 139 118 133 155 158 89 + 50 65 163 99 118 97 + 84 82 69 92 105 32 + 12 26 40 59 98 13 + 100000000 19 26 35 8 117 + 122 110 117 119 147 158 + 165 141 132 120 150 166 + 163 130 149 144 162 178 + 166 178 124 117 109 96 + 102 84 64 56 74 93 + 107 112 125 136 144 162 + 172 171 187 200 146 131 + 120 113 175 166 126 126 + 81 94 104 141 163 173 + 153 167 167 120 119 144 + 155 211 194 161 175 148 + 173 139 124 159 147 118 + 98 105 108 148 156 180 + 193 157 102 144 111 89 + 51 101 36 29 38 44 + 48 68 79 96 84 104 + 87 96 95 109 123 124 + 140 151 133 113 101 110 + 119 133 144 166 159 153 + 163 150 136 154 142 132 + 131 121 109 122 94 88 + 98 110 144 169 129 135 + 125 136 147 160 61 75 + 90 101 115 158 137 152 + 174 177 108 69 84 182 + 118 137 116 103 101 88 + 111 124 51 31 45 59 + 78 108 32 19 100000000 7 + 16 11 111 123 129 136 + 138 166 152 159 135 126 + 114 144 160 157 124 143 + 138 156 172 160 172 118 + 111 103 90 96 78 58 + 50 68 87 101 106 119 + 130 138 156 166 165 181 + 194 140 125 114 107 169 + 160 120 120 75 88 98 + 135 157 167 147 161 163 + 114 115 140 151 205 188 + 157 171 144 169 135 120 + 178 141 137 117 124 127 + 144 152 176 187 151 96 + 138 105 108 70 97 55 + 22 31 37 41 61 72 + 89 77 97 80 89 91 + 105 119 117 133 147 129 + 109 97 106 115 129 140 + 162 152 149 159 146 132 + 150 138 128 127 117 105 + 118 90 84 94 106 140 + 165 125 131 121 132 143 + 156 57 71 86 97 111 + 154 133 148 170 173 104 + 65 80 178 114 133 112 + 99 97 84 107 120 47 + 27 41 55 74 101 28 + 15 7 100000000 9 18 104 + 116 125 132 134 162 145 + 152 128 119 107 137 153 + 150 117 136 131 149 165 + 153 165 111 104 96 83 + 89 71 51 43 61 80 + 94 99 112 123 131 149 + 159 158 174 187 133 118 + 107 100 162 153 113 113 + 68 81 91 128 150 160 + 140 154 156 107 108 133 + 144 198 181 150 164 137 + 162 128 113 174 134 133 + 113 120 123 137 145 169 + 180 144 89 131 98 104 + 66 90 51 13 22 28 + 32 52 63 80 68 88 + 71 80 98 112 113 108 + 124 138 123 116 104 113 + 122 136 147 169 143 156 + 166 153 139 157 145 135 + 134 124 112 125 97 91 + 101 113 147 172 132 138 + 128 139 150 163 64 78 + 93 104 118 161 140 157 + 179 180 111 74 89 187 + 123 142 121 108 106 93 + 116 129 56 36 48 62 + 81 92 35 24 16 9 + 100000000 27 95 107 134 141 + 140 154 136 143 119 110 + 98 128 144 141 108 127 + 122 140 156 144 156 102 + 95 87 74 80 62 42 + 34 52 71 85 90 103 + 114 122 140 150 149 165 + 178 124 109 98 91 153 + 144 104 104 59 72 82 + 119 141 151 131 145 147 + 98 99 124 135 189 172 + 141 155 128 153 119 104 + 166 125 140 120 127 130 + 128 136 160 171 135 80 + 122 89 113 73 81 58 + 40 34 40 59 79 90 + 107 95 115 98 94 84 + 98 112 135 151 140 122 + 102 90 99 108 122 133 + 155 166 142 152 139 125 + 143 131 121 120 110 98 + 111 83 77 87 99 133 + 158 118 124 114 125 136 + 149 50 64 79 90 104 + 147 126 141 163 166 97 + 58 73 171 107 126 105 + 92 90 77 100 113 40 + 20 34 48 67 106 21 + 8 11 18 27 100000000 122 + 130 118 125 127 155 163 + 170 146 137 125 155 171 + 168 135 154 149 167 183 + 171 183 129 122 114 101 + 107 89 69 61 79 98 + 112 117 130 141 149 167 + 177 176 192 205 151 136 + 125 118 180 171 131 131 + 86 99 109 146 168 178 + 158 172 174 125 126 151 + 162 216 199 168 182 155 + 180 146 131 167 152 126 + 106 113 116 155 163 187 + 198 162 107 149 116 97 + 59 108 44 129 120 126 + 146 166 177 194 182 202 + 185 149 139 153 167 222 + 206 177 163 157 145 136 + 145 159 170 192 203 179 + 189 176 162 176 159 158 + 148 138 126 139 111 105 + 115 127 161 165 118 138 + 142 125 136 149 78 64 + 79 90 104 147 126 106 + 128 166 97 49 64 136 + 72 91 70 57 43 68 + 33 66 31 108 94 108 + 122 161 107 120 139 146 + 142 128 100000000 12 51 58 + 80 120 113 120 96 87 + 75 105 164 118 128 147 + 142 160 176 174 186 159 + 126 118 105 93 178 158 + 150 168 187 170 206 219 + 203 211 229 201 208 215 + 198 233 225 214 207 269 + 260 220 220 175 188 198 + 235 257 267 247 261 261 + 214 213 238 249 305 288 + 255 269 242 231 233 218 + 132 102 154 134 141 153 + 210 248 264 201 155 196 + 142 84 50 99 195 84 + 117 108 114 134 154 165 + 182 170 190 173 137 127 + 141 155 210 194 165 151 + 145 133 124 133 147 158 + 180 191 167 177 164 150 + 164 147 146 136 126 114 + 127 99 93 103 115 149 + 153 106 126 130 113 124 + 137 66 52 67 78 92 + 135 114 94 116 154 85 + 37 52 124 60 79 58 + 45 31 56 21 54 19 + 96 82 96 110 149 95 + 108 127 134 130 116 61 + 100000000 39 46 68 108 101 + 108 84 75 63 93 152 + 106 116 135 130 148 164 + 162 174 147 114 106 93 + 81 166 146 138 156 175 + 158 194 207 191 199 217 + 189 196 203 186 221 213 + 202 195 257 248 208 208 + 163 176 186 223 245 255 + 235 249 249 202 201 226 + 237 293 276 243 257 230 + 219 221 206 120 90 142 + 122 129 141 198 236 252 + 189 143 184 130 72 38 + 87 183 72 129 120 126 + 146 166 177 194 182 202 + 185 149 139 153 167 222 + 206 177 163 157 145 136 + 145 159 170 192 203 179 + 189 176 162 176 159 158 + 148 138 126 139 111 105 + 115 127 161 165 118 138 + 142 125 136 149 78 64 + 79 90 104 147 126 106 + 128 166 97 49 64 136 + 72 91 70 57 43 68 + 33 66 31 108 94 108 + 122 161 107 120 139 146 + 142 128 22 12 100000000 7 + 66 80 62 69 45 36 + 24 54 113 67 77 96 + 91 109 125 123 135 108 + 75 67 54 42 142 155 + 150 168 144 119 163 176 + 152 160 178 150 157 164 + 147 182 182 171 164 226 + 217 177 190 175 188 198 + 192 214 224 204 218 227 + 214 213 238 249 262 245 + 246 269 242 231 233 218 + 92 51 154 134 141 153 + 210 248 264 150 104 153 + 91 33 50 99 195 84 + 136 127 133 153 173 184 + 201 189 209 192 156 146 + 160 174 229 213 184 170 + 164 152 143 152 166 177 + 199 210 186 196 183 169 + 183 166 165 155 145 133 + 146 118 112 122 134 168 + 172 125 145 149 132 143 + 156 85 71 86 97 111 + 154 133 113 135 173 104 + 56 71 143 79 98 77 + 64 50 75 40 73 38 + 115 101 115 129 168 114 + 127 146 153 149 135 15 + 19 7 100000000 59 73 55 + 62 38 29 17 47 106 + 60 70 89 84 102 118 + 116 128 101 68 60 47 + 35 135 148 157 175 137 + 112 156 169 145 153 171 + 143 150 157 140 175 175 + 164 157 219 210 170 183 + 182 195 205 185 207 217 + 197 211 220 221 220 245 + 256 255 238 239 266 249 + 238 240 225 85 44 161 + 141 148 160 217 255 271 + 143 97 146 84 26 57 + 106 202 91 143 134 140 + 160 180 191 208 196 216 + 199 163 153 167 181 236 + 220 191 177 171 159 150 + 159 173 184 206 217 193 + 203 190 176 190 173 172 + 162 152 140 153 125 119 + 129 141 175 179 132 152 + 156 139 150 163 92 78 + 93 104 118 161 140 102 + 124 180 111 63 78 132 + 68 87 66 53 39 82 + 29 14 45 122 108 122 + 136 175 121 134 153 160 + 156 142 30 26 14 15 + 100000000 66 48 55 31 22 + 32 40 99 53 63 82 + 77 95 111 109 121 94 + 74 66 62 50 128 141 + 164 182 130 105 149 162 + 138 146 164 136 143 150 + 133 168 168 157 150 212 + 203 163 176 189 202 203 + 178 200 210 190 204 213 + 219 227 252 263 248 231 + 232 259 256 245 247 232 + 78 37 168 148 155 167 + 224 262 278 136 90 139 + 77 41 46 113 209 98 + 167 158 164 184 204 215 + 232 220 240 223 187 177 + 191 205 260 244 215 201 + 195 183 174 183 197 208 + 230 241 217 227 214 200 + 214 197 196 186 176 164 + 177 149 143 153 165 199 + 176 156 176 180 163 174 + 187 116 102 117 128 142 + 158 137 97 119 177 135 + 87 102 127 92 82 50 + 77 63 106 53 38 69 + 146 132 146 160 199 145 + 158 177 184 180 166 54 + 50 38 39 24 100000000 18 + 25 43 46 56 60 81 + 73 83 64 97 115 101 + 129 141 114 94 86 86 + 74 148 161 188 206 150 + 125 169 182 158 166 184 + 153 156 140 123 181 188 + 177 170 231 222 183 196 + 213 226 223 198 220 230 + 210 224 233 239 251 276 + 287 267 250 252 279 280 + 269 271 256 12 31 192 + 172 179 191 248 286 302 + 130 110 159 97 65 70 + 137 233 122 185 176 182 + 202 222 233 234 238 258 + 241 205 195 209 223 278 + 262 233 219 213 201 192 + 201 215 226 248 259 235 + 245 232 218 232 215 214 + 204 194 182 195 167 161 + 171 183 217 194 174 194 + 198 181 192 205 134 120 + 135 146 160 176 155 115 + 137 195 153 105 120 145 + 110 100 68 95 81 124 + 71 56 87 164 150 164 + 178 217 163 176 195 202 + 198 184 72 68 56 57 + 42 18 100000000 7 25 60 + 72 42 63 55 65 46 + 79 97 83 111 123 96 + 76 68 102 90 130 143 + 206 224 132 107 151 164 + 140 148 166 135 138 122 + 105 163 170 159 152 213 + 204 165 178 197 210 205 + 180 202 212 192 206 215 + 221 253 278 274 249 232 + 234 261 282 287 273 258 + 30 31 210 190 197 209 + 266 290 314 112 92 141 + 79 81 88 155 225 140 + 182 173 179 199 219 230 + 227 235 255 238 202 192 + 206 220 275 259 230 216 + 210 198 189 198 212 223 + 245 256 232 242 229 215 + 229 212 211 201 191 179 + 192 164 158 168 180 214 + 201 171 191 195 178 189 + 202 131 117 132 143 157 + 183 162 122 144 202 150 + 102 117 152 107 107 75 + 92 78 121 68 53 84 + 161 147 161 175 214 160 + 173 192 199 195 181 69 + 65 53 54 39 25 7 + 100000000 18 53 65 35 56 + 48 58 39 72 90 76 + 104 116 89 69 61 95 + 83 123 136 203 221 125 + 100 144 157 133 141 159 + 128 131 115 98 156 163 + 152 145 206 197 158 171 + 190 203 198 173 195 205 + 185 199 208 214 246 271 + 267 242 225 227 254 275 + 284 266 251 37 24 207 + 187 194 206 263 283 307 + 105 85 134 72 74 85 + 152 218 137 164 155 161 + 181 201 212 209 217 237 + 220 184 174 188 202 257 + 241 212 198 192 180 171 + 180 194 205 227 238 214 + 224 211 197 211 194 193 + 183 173 161 174 146 140 + 150 162 196 200 153 173 + 177 160 171 184 113 99 + 114 125 139 182 161 123 + 145 201 132 84 99 153 + 89 108 85 74 60 103 + 50 35 66 143 129 143 + 157 196 142 155 174 181 + 177 163 51 47 35 36 + 21 35 17 24 100000000 35 + 47 17 76 30 40 59 + 54 72 88 86 98 71 + 51 43 77 65 105 118 + 185 203 107 82 126 139 + 115 123 141 113 120 127 + 110 145 145 134 127 189 + 180 140 153 172 185 180 + 155 177 187 167 181 190 + 196 228 253 250 225 208 + 209 236 257 266 248 233 + 47 6 189 169 176 188 + 245 265 289 113 67 116 + 54 56 67 134 200 119 + 173 164 170 190 210 221 + 210 220 240 229 193 183 + 197 211 260 250 221 207 + 201 189 180 189 203 214 + 236 247 223 233 220 206 + 220 203 202 192 182 170 + 183 155 149 159 171 205 + 209 162 182 186 169 180 + 193 122 108 123 134 148 + 191 170 132 154 210 141 + 93 108 162 98 117 94 + 83 69 112 59 44 75 + 152 138 152 166 205 151 + 164 183 190 186 172 45 + 56 44 45 30 44 26 + 33 9 100000000 12 18 77 + 31 41 60 55 73 89 + 87 99 72 52 44 42 + 30 106 119 190 208 108 + 83 127 140 116 124 142 + 114 121 128 111 146 146 + 135 128 190 181 141 154 + 173 186 181 156 178 188 + 168 182 191 197 229 254 + 251 226 209 210 237 258 + 275 249 234 56 15 198 + 178 185 197 254 266 290 + 114 68 117 55 21 76 + 143 201 128 162 153 159 + 179 199 210 222 215 235 + 218 182 172 186 200 255 + 239 210 196 190 178 169 + 178 192 203 225 236 212 + 222 209 195 209 192 191 + 181 171 159 172 144 138 + 148 160 194 198 151 171 + 175 158 169 182 111 97 + 112 123 137 180 159 139 + 161 199 130 82 97 169 + 105 124 103 90 76 101 + 66 56 64 141 127 141 + 155 194 140 153 172 179 + 175 161 33 45 56 57 + 42 56 38 45 21 12 + 100000000 30 89 43 53 72 + 67 85 101 99 111 84 + 51 43 30 18 118 131 + 183 201 120 95 139 152 + 128 136 154 126 133 140 + 123 158 158 147 140 202 + 193 153 166 185 198 193 + 168 190 200 180 194 203 + 209 241 266 263 238 221 + 222 249 270 264 261 246 + 68 27 187 167 174 186 + 243 278 297 126 80 129 + 67 9 83 132 213 117 + 191 182 188 188 208 219 + 192 202 222 227 211 201 + 215 229 242 258 239 225 + 219 207 198 207 221 232 + 254 265 241 251 238 224 + 238 221 220 210 200 188 + 201 173 167 177 189 223 + 227 180 200 204 187 198 + 211 140 126 141 152 166 + 209 188 150 172 228 159 + 111 126 180 116 135 112 + 101 87 130 77 62 93 + 170 156 170 184 223 169 + 182 201 208 204 190 63 + 74 62 63 48 62 44 + 51 27 18 30 100000000 59 + 13 23 42 37 55 71 + 69 81 54 34 26 60 + 48 88 101 172 190 90 + 65 109 122 98 106 124 + 96 103 110 93 128 128 + 117 110 172 163 123 136 + 155 168 163 138 160 170 + 150 164 173 179 211 236 + 233 208 191 192 219 240 + 265 231 216 74 33 216 + 196 203 215 262 248 272 + 96 50 99 37 39 94 + 161 183 146 193 198 204 + 188 208 219 192 202 222 + 227 227 217 231 245 242 + 258 255 241 235 223 214 + 223 237 248 270 277 257 + 267 254 240 254 237 236 + 226 216 204 217 189 183 + 193 205 239 243 196 216 + 220 203 214 227 156 142 + 157 168 182 225 204 166 + 188 244 175 127 142 196 + 132 151 128 117 103 146 + 93 78 109 186 172 186 + 200 239 185 198 217 215 + 206 206 79 90 78 79 + 64 78 60 67 43 34 + 46 16 100000000 13 23 42 + 37 55 71 69 81 54 + 50 42 76 64 88 101 + 172 190 90 65 109 122 + 98 106 124 96 103 110 + 93 128 128 117 110 172 + 163 123 136 155 168 163 + 138 160 170 150 164 173 + 179 211 236 233 208 191 + 192 219 240 265 231 216 + 90 49 232 212 219 231 + 262 248 272 96 50 99 + 37 55 110 177 183 162 + 180 189 195 175 195 206 + 179 189 209 214 223 247 + 261 234 229 245 259 244 + 255 253 244 253 267 278 + 300 264 287 297 284 270 + 284 267 266 256 246 234 + 247 219 213 223 235 269 + 269 226 246 250 233 244 + 257 186 172 187 198 212 + 251 230 190 212 270 205 + 157 172 220 175 175 143 + 160 146 176 136 121 139 + 216 202 216 230 235 202 + 215 209 202 193 220 108 + 120 121 122 107 93 75 + 68 86 80 92 62 46 + 100000000 10 29 24 42 58 + 56 68 41 64 88 87 + 93 75 88 159 177 77 + 52 96 109 85 93 111 + 83 90 97 80 115 115 + 104 97 159 150 110 123 + 142 155 150 125 147 157 + 137 151 160 166 198 223 + 220 195 178 179 206 227 + 252 218 203 105 92 262 + 242 249 261 249 235 259 + 83 37 86 24 101 153 + 207 170 192 170 179 185 + 165 185 196 169 179 199 + 204 213 237 251 224 219 + 235 249 234 245 243 234 + 243 257 268 290 254 277 + 287 274 260 274 257 256 + 246 236 224 237 209 203 + 213 225 259 259 216 236 + 240 223 234 247 176 162 + 177 188 202 241 220 180 + 202 260 195 147 162 210 + 165 165 133 150 136 166 + 126 111 129 206 192 206 + 220 225 192 205 199 192 + 183 210 98 110 111 112 + 97 83 65 58 76 70 + 82 52 36 49 100000000 19 + 14 32 48 46 58 31 + 54 78 77 83 65 78 + 149 167 67 42 86 99 + 75 83 101 73 80 87 + 70 105 105 94 87 149 + 140 100 113 132 145 140 + 115 137 147 127 141 150 + 156 188 213 210 185 168 + 169 196 217 242 208 193 + 95 82 252 232 239 251 + 239 225 249 73 27 76 + 14 91 143 197 160 182 + 210 212 218 205 225 236 + 209 219 239 244 241 231 + 245 259 259 275 269 255 + 249 237 228 237 251 262 + 284 294 271 281 268 254 + 268 251 250 240 230 218 + 231 203 197 207 219 253 + 240 210 230 234 217 228 + 241 170 156 171 182 196 + 222 201 161 183 241 189 + 141 156 191 146 146 114 + 131 117 160 107 92 123 + 200 186 200 214 253 199 + 212 231 232 223 220 96 + 104 92 93 78 64 46 + 39 57 51 63 33 17 + 30 40 100000000 54 53 37 + 67 79 71 67 59 93 + 81 105 118 189 207 107 + 82 126 139 96 104 122 + 89 92 76 59 117 145 + 134 127 167 158 140 153 + 172 185 180 155 168 178 + 167 181 190 196 228 239 + 228 203 186 200 227 254 + 282 248 233 76 63 246 + 226 233 245 279 265 286 + 66 67 116 54 72 124 + 191 200 176 207 216 222 + 202 222 233 206 216 236 + 241 250 249 263 261 256 + 272 286 271 267 255 246 + 255 269 280 302 287 289 + 299 286 272 286 269 268 + 258 248 236 249 221 215 + 225 237 271 258 228 248 + 252 235 246 259 188 174 + 189 200 214 240 219 179 + 201 259 207 159 174 209 + 164 164 132 149 135 178 + 125 110 141 218 204 218 + 232 262 217 230 236 229 + 220 238 114 122 110 111 + 96 82 64 57 75 69 + 81 51 35 48 58 18 + 100000000 18 34 32 44 68 + 85 77 111 99 102 115 + 186 204 104 79 123 136 + 61 69 87 59 66 73 + 56 91 142 131 124 141 + 132 137 150 169 182 177 + 152 142 152 164 178 187 + 193 225 213 202 177 160 + 174 201 228 259 245 230 + 94 81 264 244 251 263 + 276 262 260 59 63 113 + 72 90 142 209 197 194 + 189 198 204 184 204 215 + 188 198 218 223 232 256 + 270 243 238 254 268 253 + 264 262 253 262 276 287 + 309 269 296 306 293 279 + 293 276 275 265 255 243 + 256 228 222 232 244 278 + 282 235 255 259 242 253 + 266 195 181 196 207 221 + 264 243 214 236 283 214 + 166 181 244 189 199 167 + 174 160 185 150 145 148 + 225 211 225 239 244 211 + 224 218 211 202 229 117 + 129 145 146 131 117 99 + 92 110 104 116 86 70 + 83 86 53 53 100000000 16 + 14 26 50 73 109 96 + 102 84 97 168 186 86 + 61 105 118 43 51 69 + 41 48 55 38 73 124 + 113 106 123 114 119 132 + 151 164 159 134 124 134 + 146 160 169 175 207 195 + 184 159 142 156 183 210 + 241 227 212 129 116 271 + 251 258 270 258 244 242 + 41 45 95 100 111 167 + 216 179 201 205 214 220 + 200 220 231 204 214 234 + 239 248 268 282 259 254 + 270 284 269 280 274 265 + 274 288 299 321 276 305 + 318 305 291 305 288 287 + 277 267 255 268 240 234 + 244 256 290 277 247 267 + 271 254 265 278 207 193 + 208 219 233 259 238 198 + 220 278 226 178 193 228 + 183 183 151 168 154 197 + 144 129 160 237 223 237 + 251 260 227 240 234 227 + 218 245 133 141 129 130 + 115 101 83 76 94 88 + 100 70 54 67 77 37 + 69 16 100000000 30 42 66 + 89 96 112 118 100 113 + 184 202 102 77 121 134 + 59 67 85 52 55 39 + 22 80 140 129 122 130 + 121 135 148 167 180 175 + 150 131 141 158 172 181 + 191 223 202 191 166 149 + 163 190 217 248 243 228 + 113 100 283 263 270 282 + 274 260 249 29 61 111 + 91 109 161 228 195 213 + 175 184 190 170 190 201 + 174 184 204 209 218 242 + 256 229 224 240 254 239 + 250 248 239 248 262 273 + 295 255 282 292 279 265 + 279 262 261 251 241 229 + 242 214 208 218 230 264 + 268 221 241 245 228 239 + 252 181 167 182 193 207 + 250 229 209 231 269 200 + 152 167 239 175 194 171 + 160 146 171 136 149 134 + 211 197 211 225 230 197 + 210 204 197 188 215 103 + 115 149 150 135 121 103 + 96 114 108 106 90 74 + 87 72 57 39 33 49 + 100000000 12 36 59 95 82 + 88 70 83 154 172 72 + 47 91 104 29 37 55 + 27 34 50 34 59 110 + 99 92 109 100 105 118 + 137 150 145 120 110 120 + 132 146 155 161 193 181 + 170 145 128 142 169 196 + 227 213 198 133 120 257 + 237 244 256 244 230 228 + 27 31 81 86 97 153 + 202 165 187 163 172 178 + 158 178 189 162 172 192 + 197 206 230 244 217 212 + 228 242 227 238 236 227 + 236 250 261 283 247 270 + 280 267 253 267 250 249 + 239 229 217 230 202 196 + 206 218 252 256 209 229 + 233 216 227 240 169 155 + 170 181 195 238 217 197 + 219 257 188 140 155 227 + 163 182 159 148 134 159 + 124 137 122 199 185 199 + 213 218 185 198 192 185 + 176 203 91 103 137 138 + 123 109 91 84 102 96 + 94 78 62 75 60 45 + 27 21 37 35 100000000 24 + 47 83 70 76 58 71 + 142 160 60 35 79 92 + 17 25 43 53 60 76 + 59 59 98 87 80 109 + 100 93 106 125 138 133 + 108 110 120 120 134 143 + 149 181 181 170 145 128 + 142 169 196 227 201 186 + 121 108 245 225 232 244 + 232 218 228 62 19 69 + 74 85 141 190 153 175 + 139 148 154 134 154 165 + 138 148 168 173 182 206 + 220 193 188 204 218 203 + 214 212 203 212 226 237 + 259 223 246 256 243 229 + 243 226 225 215 205 193 + 206 178 172 182 194 228 + 232 185 205 209 192 203 + 216 145 131 146 157 171 + 214 193 173 195 233 164 + 116 131 203 139 158 137 + 124 110 135 100 126 98 + 175 161 175 189 194 161 + 174 168 161 152 179 67 + 79 118 125 112 119 101 + 94 91 82 70 88 72 + 85 36 55 50 68 84 + 82 94 100000000 23 59 46 + 52 34 47 118 136 36 + 11 55 68 79 87 105 + 109 114 123 106 89 74 + 63 56 118 109 69 82 + 101 114 109 84 106 116 + 96 110 119 125 157 182 + 179 154 137 138 165 186 + 211 177 162 131 97 221 + 201 208 220 208 194 218 + 109 63 45 50 61 117 + 166 129 151 183 192 198 + 178 198 209 182 192 212 + 217 226 250 264 237 232 + 248 262 247 258 256 247 + 256 270 281 303 267 290 + 300 287 273 287 270 269 + 259 249 237 250 222 216 + 226 238 272 272 229 249 + 253 236 247 260 189 175 + 190 201 215 254 233 193 + 215 273 208 160 175 223 + 178 178 146 163 149 179 + 139 124 142 219 205 219 + 233 238 205 218 212 205 + 196 223 111 123 124 125 + 110 96 78 71 89 83 + 95 65 49 62 13 32 + 27 45 61 59 71 44 + 100000000 91 90 96 78 91 + 162 180 80 55 99 112 + 88 96 114 86 93 100 + 83 118 118 107 100 162 + 153 113 126 145 158 153 + 128 150 160 140 154 163 + 169 201 226 223 198 181 + 182 209 230 255 221 206 + 108 95 265 245 252 264 + 252 238 262 86 40 89 + 27 104 156 210 173 195 + 191 200 206 186 206 217 + 190 200 220 225 234 258 + 272 245 240 256 270 255 + 266 264 255 264 278 289 + 311 275 298 308 295 281 + 295 278 277 267 257 245 + 258 230 224 234 246 280 + 280 237 257 261 244 255 + 268 197 183 198 209 223 + 262 241 201 223 281 216 + 168 183 231 186 186 154 + 171 157 187 147 132 150 + 227 213 227 241 246 213 + 226 220 213 204 231 119 + 131 132 133 118 104 86 + 79 97 91 103 73 57 + 70 21 40 35 53 69 + 67 79 52 8 100000000 98 + 104 86 99 170 188 88 + 63 107 120 96 104 122 + 94 101 108 91 126 126 + 115 108 170 161 121 134 + 153 166 161 136 158 168 + 148 162 171 177 209 234 + 231 206 189 190 217 238 + 263 229 214 116 103 273 + 253 260 272 260 246 270 + 94 48 97 35 112 164 + 218 181 203 204 213 219 + 199 219 230 203 213 233 + 238 247 271 285 258 253 + 269 283 268 279 277 268 + 277 291 302 324 288 311 + 321 308 294 308 291 290 + 280 270 258 271 243 237 + 247 259 293 293 250 270 + 274 257 268 281 210 196 + 211 222 236 275 254 214 + 236 294 229 181 196 244 + 199 199 167 184 170 200 + 160 145 163 240 226 240 + 254 259 226 239 233 226 + 217 244 132 144 145 146 + 131 117 99 92 110 104 + 116 86 70 83 34 53 + 48 66 82 80 92 65 + 21 13 100000000 117 99 112 + 183 201 101 76 120 133 + 109 117 135 107 114 121 + 104 139 139 128 121 183 + 174 134 147 166 179 174 + 149 171 181 161 175 184 + 190 222 247 244 219 202 + 203 230 251 276 242 227 + 129 116 286 266 273 285 + 273 259 283 107 61 110 + 48 125 177 231 194 216 + 144 135 141 161 181 192 + 209 197 217 200 164 154 + 168 182 237 221 192 178 + 172 160 151 160 174 185 + 207 218 194 204 191 177 + 191 174 173 163 153 141 + 154 126 120 130 142 176 + 180 133 153 157 140 151 + 164 93 79 94 105 119 + 162 141 121 143 181 112 + 64 79 151 87 106 85 + 72 58 83 48 74 46 + 123 109 123 137 176 122 + 135 154 161 157 143 15 + 27 66 73 60 74 56 + 63 39 30 18 48 100 + 61 64 83 78 96 112 + 110 122 95 51 43 30 + 100000000 129 142 165 183 131 + 106 150 163 139 147 165 + 137 144 151 134 169 169 + 158 151 213 204 164 177 + 190 203 204 179 201 211 + 191 205 214 220 228 253 + 264 249 232 233 260 257 + 246 248 233 86 45 169 + 149 156 168 225 263 279 + 137 91 140 78 9 65 + 114 210 99 151 153 159 + 146 166 177 150 160 180 + 185 182 172 186 200 200 + 216 210 196 190 178 169 + 178 192 203 225 235 212 + 222 209 195 209 192 191 + 181 171 159 172 144 138 + 148 160 194 198 151 171 + 175 158 169 182 111 97 + 112 123 137 180 159 139 + 161 199 130 82 97 169 + 105 124 103 90 76 101 + 66 92 64 141 127 141 + 155 194 140 153 172 173 + 164 161 33 45 84 91 + 78 92 74 81 57 48 + 36 66 82 79 46 65 + 60 78 94 92 104 77 + 33 25 12 18 100000000 59 + 130 148 48 23 67 80 + 91 99 117 119 126 133 + 116 101 86 75 68 130 + 121 81 94 113 126 121 + 96 118 128 108 122 131 + 137 169 194 191 166 149 + 150 177 198 223 189 174 + 104 63 187 167 174 186 + 220 206 230 119 73 57 + 60 27 83 132 141 117 + 171 173 179 166 186 197 + 170 180 200 205 202 192 + 206 220 220 236 230 216 + 210 198 189 198 212 223 + 245 255 232 242 229 215 + 229 212 211 201 191 179 + 192 164 158 168 180 214 + 218 171 191 195 178 189 + 202 131 117 132 143 157 + 200 179 159 181 219 150 + 102 117 189 125 144 123 + 110 96 121 86 112 84 + 161 147 161 175 214 160 + 173 192 193 184 181 53 + 65 104 111 98 112 94 + 101 77 68 56 86 102 + 99 66 85 80 98 114 + 112 124 97 53 45 32 + 38 20 100000000 150 168 68 + 43 87 100 111 119 137 + 139 146 153 136 121 106 + 95 88 150 141 101 114 + 133 146 141 116 138 148 + 128 142 151 157 189 214 + 211 186 169 170 197 218 + 243 209 194 124 83 207 + 187 194 206 240 226 250 + 139 93 77 80 47 103 + 152 161 137 21 30 36 + 16 36 47 64 52 72 + 55 64 106 120 97 92 + 108 122 107 118 112 121 + 125 139 150 172 127 156 + 169 156 142 160 153 142 + 142 132 120 133 105 99 + 109 121 155 180 140 146 + 136 147 158 171 72 86 + 101 112 126 169 148 167 + 189 188 119 106 121 197 + 133 152 131 118 104 125 + 94 120 88 68 56 70 + 89 76 43 56 50 43 + 34 61 61 73 112 119 + 106 120 102 109 85 76 + 64 94 110 107 74 93 + 88 106 122 110 122 68 + 61 53 40 46 28 8 + 100000000 18 37 51 56 69 + 80 88 106 116 115 131 + 144 90 75 64 57 119 + 110 70 70 25 38 48 + 85 107 117 97 111 120 + 64 83 108 119 155 138 + 125 139 112 137 103 88 + 132 91 148 128 135 138 + 112 120 144 137 101 46 + 88 55 111 81 53 66 + 45 54 60 40 60 71 + 59 69 89 79 88 130 + 144 114 109 125 139 124 + 135 136 145 142 156 167 + 189 144 173 186 173 159 + 177 177 159 166 156 144 + 157 129 123 133 145 179 + 204 164 170 160 171 182 + 195 96 110 125 136 150 + 193 172 191 213 212 143 + 130 145 221 157 176 155 + 142 128 149 118 144 112 + 92 80 94 113 100 67 + 80 74 67 58 85 85 + 97 136 143 130 144 126 + 133 109 100 88 118 122 + 131 86 105 100 118 134 + 92 104 50 73 77 64 + 70 52 32 24 100000000 19 + 61 38 51 62 70 88 + 98 97 113 126 72 57 + 46 39 101 92 52 52 + 7 20 30 67 89 99 + 79 93 102 46 78 103 + 114 137 120 120 134 107 + 132 98 83 156 115 172 + 152 159 162 129 115 139 + 119 113 28 100 79 135 + 105 35 90 103 112 118 + 98 118 129 102 112 132 + 137 146 188 202 157 152 + 168 182 167 178 188 194 + 185 199 210 232 187 216 + 229 216 202 220 225 202 + 224 214 202 215 187 181 + 191 203 237 262 216 228 + 218 223 234 247 154 162 + 177 188 202 245 224 204 + 226 264 195 147 162 234 + 170 189 168 155 141 166 + 131 157 129 150 138 152 + 171 158 125 138 132 125 + 116 143 98 110 149 156 + 143 150 132 125 122 113 + 101 119 103 116 67 86 + 81 99 115 73 85 31 + 54 90 77 83 65 78 + 82 100 100000000 42 19 32 + 43 51 69 79 78 94 + 107 53 38 27 20 82 + 73 33 46 65 78 73 + 48 70 80 60 74 83 + 89 121 146 143 118 101 + 102 129 150 175 141 126 + 162 128 230 210 217 207 + 172 158 182 100 94 9 + 81 92 148 163 93 148 + 128 137 143 123 143 154 + 127 137 157 162 171 195 + 209 182 177 193 207 192 + 203 201 192 201 215 226 + 248 212 235 245 232 218 + 232 215 214 204 194 182 + 195 167 161 171 183 217 + 221 174 194 198 181 192 + 205 134 120 135 146 160 + 203 182 162 184 222 153 + 105 120 192 128 147 126 + 113 99 124 89 115 87 + 164 150 164 178 183 150 + 163 157 150 141 168 56 + 68 107 114 101 115 97 + 104 80 71 59 89 105 + 102 69 88 83 101 117 + 98 110 56 56 48 35 + 41 23 36 107 125 25 + 100000000 44 57 68 76 94 + 104 103 119 132 78 63 + 52 45 107 98 58 71 + 90 103 98 73 95 105 + 85 99 108 114 146 171 + 168 143 126 127 154 175 + 200 166 151 127 86 210 + 190 197 209 197 183 207 + 125 96 34 83 50 106 + 155 118 140 151 160 166 + 146 166 177 150 160 180 + 185 194 218 232 205 200 + 216 230 215 226 224 215 + 224 238 249 271 235 258 + 268 255 241 255 238 237 + 227 217 205 218 190 184 + 194 206 240 244 197 217 + 221 204 215 228 157 143 + 158 169 183 226 205 185 + 207 245 176 128 143 215 + 151 170 149 136 122 147 + 112 138 110 187 173 187 + 201 206 173 186 180 173 + 164 191 79 91 130 137 + 124 131 113 106 103 94 + 82 100 84 97 48 67 + 62 80 96 54 66 12 + 35 71 58 64 46 59 + 130 148 48 23 100000000 13 + 24 32 50 60 67 83 + 88 66 86 75 68 116 + 107 81 94 113 126 121 + 96 117 127 108 122 131 + 137 169 188 177 152 135 + 149 176 198 223 189 174 + 143 109 233 213 220 232 + 220 206 230 81 75 57 + 62 73 129 178 141 163 + 188 197 203 183 203 214 + 187 197 217 222 231 273 + 287 242 237 253 267 252 + 263 273 279 270 284 287 + 309 249 278 291 301 287 + 305 303 287 292 282 270 + 283 255 249 259 271 305 + 309 262 282 286 269 280 + 293 222 208 223 234 248 + 291 270 250 272 310 241 + 193 208 280 216 235 212 + 201 187 212 177 190 175 + 235 223 237 256 243 210 + 223 217 210 201 228 144 + 156 190 191 176 162 144 + 137 155 149 147 131 115 + 128 113 98 80 74 90 + 41 53 77 100 136 123 + 129 111 124 167 185 113 + 88 132 100000000 11 19 37 + 47 54 70 75 53 145 + 134 133 103 94 118 131 + 150 163 158 133 104 114 + 131 145 154 174 200 175 + 164 139 122 136 163 190 + 221 226 211 174 161 298 + 278 285 292 257 237 222 + 68 72 122 127 138 194 + 243 178 228 177 186 192 + 172 192 203 176 186 206 + 211 220 262 276 231 226 + 242 256 241 252 262 268 + 259 273 276 298 238 267 + 280 290 276 294 292 276 + 281 271 259 272 244 238 + 248 260 294 298 251 271 + 275 258 269 282 211 197 + 212 223 237 280 259 239 + 261 299 230 182 197 269 + 205 224 201 190 176 201 + 166 179 164 224 212 226 + 245 232 199 212 206 199 + 190 217 133 145 179 180 + 165 151 133 126 144 138 + 136 120 104 117 102 87 + 69 63 79 30 42 66 + 89 125 112 118 100 113 + 156 174 102 77 121 134 + 100000000 8 26 36 43 59 + 64 42 134 123 122 92 + 83 107 120 139 152 147 + 122 93 103 120 134 143 + 163 189 164 153 128 111 + 125 152 179 210 215 200 + 163 150 287 267 274 281 + 246 226 211 57 61 111 + 116 127 183 232 167 217 + 169 178 184 164 184 195 + 168 178 198 203 212 254 + 268 223 218 234 248 233 + 244 254 260 251 265 268 + 290 230 259 272 282 268 + 286 284 268 273 263 251 + 264 236 230 240 252 286 + 290 243 263 267 250 261 + 274 203 189 204 215 229 + 272 251 231 253 291 222 + 174 189 261 197 216 193 + 182 168 193 158 171 156 + 216 204 218 237 224 191 + 204 198 191 182 209 125 + 137 171 172 157 143 125 + 118 136 130 128 112 96 + 109 94 79 61 55 71 + 22 34 58 81 117 104 + 110 92 105 148 166 94 + 69 113 126 51 100000000 18 + 28 35 51 56 34 126 + 115 114 84 75 99 112 + 131 144 139 114 85 95 + 112 126 135 155 181 156 + 145 120 103 117 144 171 + 202 207 192 155 142 279 + 259 266 273 238 218 203 + 49 53 103 108 119 175 + 224 159 209 151 160 166 + 146 166 177 150 160 180 + 185 194 236 250 205 200 + 216 230 215 226 236 242 + 233 247 250 272 212 241 + 254 264 250 268 273 250 + 272 262 250 263 235 229 + 239 251 285 305 258 276 + 266 265 276 289 202 204 + 219 230 244 287 266 246 + 268 306 237 189 204 276 + 212 231 208 197 183 208 + 173 186 171 198 186 200 + 219 206 173 186 180 173 + 164 191 140 152 186 187 + 172 158 140 133 151 145 + 143 127 111 124 109 94 + 76 70 72 37 49 73 + 96 132 119 125 107 120 + 130 148 109 84 128 141 + 66 74 100000000 10 17 33 + 50 16 108 97 129 66 + 57 81 94 113 126 121 + 96 67 77 94 108 117 + 137 163 138 127 102 85 + 99 126 153 184 189 174 + 170 157 278 258 265 255 + 220 200 185 57 68 118 + 123 134 190 211 141 196 + 167 176 182 162 182 193 + 166 176 196 201 210 252 + 266 221 216 232 246 231 + 242 252 258 249 263 266 + 288 228 257 270 280 266 + 284 289 266 278 268 256 + 269 241 235 245 257 291 + 295 248 268 272 255 266 + 279 208 194 209 220 234 + 277 256 236 258 296 227 + 179 194 266 202 221 198 + 187 173 198 163 176 161 + 214 202 216 235 222 189 + 202 196 189 180 207 130 + 142 176 177 162 148 130 + 123 141 135 133 117 101 + 114 99 84 66 60 62 + 27 39 63 86 122 109 + 115 97 110 146 164 99 + 74 118 131 56 64 82 + 100000000 7 23 40 32 124 + 113 119 82 73 97 110 + 129 142 137 112 83 93 + 110 124 133 153 179 154 + 143 118 101 115 142 169 + 200 205 190 160 147 284 + 264 271 271 236 216 201 + 47 58 108 113 124 180 + 227 157 212 160 169 175 + 155 175 186 159 169 189 + 194 203 245 259 214 209 + 225 239 224 235 245 251 + 242 256 259 281 221 250 + 263 273 259 277 282 259 + 281 271 259 272 244 238 + 248 260 294 302 255 275 + 275 262 273 286 211 201 + 216 227 241 284 263 243 + 265 303 234 186 201 273 + 209 228 205 194 180 205 + 170 183 168 207 195 209 + 228 215 182 195 189 182 + 173 200 137 149 183 184 + 169 155 137 130 148 142 + 140 124 108 121 106 91 + 73 67 55 34 46 70 + 93 129 116 122 104 117 + 139 157 106 81 125 138 + 63 71 89 7 100000000 16 + 33 25 117 106 126 75 + 66 90 103 122 135 130 + 105 76 86 103 117 126 + 146 172 147 136 111 94 + 108 135 162 193 198 183 + 167 154 287 267 274 264 + 229 209 194 40 65 115 + 120 131 187 220 150 205 + 176 185 191 171 191 202 + 175 185 205 210 219 261 + 275 230 225 241 255 240 + 251 261 267 258 272 275 + 297 237 266 279 289 275 + 293 298 275 297 287 275 + 288 260 254 264 276 310 + 316 271 291 291 278 289 + 302 227 217 232 243 257 + 298 277 237 259 317 250 + 202 217 267 222 222 190 + 207 193 221 183 168 184 + 223 211 225 244 231 198 + 211 205 198 189 216 153 + 165 168 169 154 140 122 + 115 133 127 139 109 93 + 106 116 76 89 55 39 + 50 62 86 109 135 132 + 138 120 133 155 173 122 + 97 141 154 79 87 105 + 23 16 100000000 17 41 133 + 122 142 91 82 106 119 + 138 151 146 121 92 102 + 119 133 142 162 188 163 + 152 127 110 124 151 178 + 209 214 199 152 139 303 + 283 290 280 245 225 210 + 24 81 131 130 147 200 + 236 166 221 193 202 208 + 188 208 219 192 202 222 + 227 236 276 290 247 242 + 258 272 257 268 278 273 + 275 289 292 314 254 283 + 296 306 292 310 296 292 + 285 275 263 276 248 242 + 252 264 298 299 255 275 + 279 262 273 286 215 201 + 216 227 241 281 260 220 + 242 300 234 186 201 250 + 205 205 173 190 176 205 + 166 151 168 240 228 242 + 259 248 215 228 222 215 + 206 233 137 149 151 152 + 137 123 105 98 116 110 + 122 92 76 89 99 59 + 73 38 22 34 46 70 + 93 118 116 122 104 117 + 172 190 106 81 125 138 + 63 71 89 30 33 17 + 100000000 58 144 133 126 108 + 99 123 136 155 168 163 + 138 109 119 136 150 159 + 179 205 180 169 144 127 + 141 168 195 226 231 216 + 135 122 291 271 278 290 + 262 242 227 7 65 115 + 113 131 183 236 183 221 + 135 144 150 130 150 161 + 134 144 164 169 178 220 + 234 189 184 200 214 199 + 210 220 226 217 231 234 + 256 196 225 238 248 234 + 252 257 234 256 246 234 + 247 219 213 223 235 269 + 294 254 260 250 261 272 + 285 186 200 215 226 240 + 283 262 268 290 302 233 + 211 226 298 234 253 230 + 219 205 230 195 208 193 + 182 170 184 203 190 157 + 170 164 157 148 175 162 + 174 208 209 194 180 162 + 155 173 167 165 149 133 + 146 131 116 98 92 80 + 59 71 95 118 154 141 + 147 129 122 114 132 93 + 106 112 125 88 96 114 + 32 25 41 58 100000000 92 + 81 113 50 41 65 78 + 97 110 105 80 51 61 + 78 92 101 121 147 122 + 111 86 69 83 110 137 + 168 173 158 192 179 262 + 242 249 239 204 184 169 + 65 90 102 145 156 212 + 195 125 180 129 138 144 + 124 144 155 128 138 158 + 163 172 214 228 183 178 + 194 208 193 204 214 220 + 211 225 228 250 190 219 + 232 242 228 246 251 228 + 250 240 228 241 213 207 + 217 229 263 288 248 254 + 244 255 266 279 180 194 + 209 220 234 277 256 248 + 270 296 227 191 206 278 + 214 233 210 199 185 210 + 175 188 173 176 164 178 + 197 184 151 164 158 151 + 142 169 142 154 188 189 + 174 160 142 135 153 147 + 145 129 113 126 111 96 + 78 72 88 39 51 75 + 98 134 121 127 109 116 + 108 126 87 86 106 119 + 68 17 35 45 40 56 + 73 15 100000000 75 107 44 + 35 59 72 91 104 99 + 74 45 55 72 86 95 + 115 141 116 105 80 63 + 77 104 131 162 167 152 + 172 159 256 236 243 233 + 198 178 163 66 70 96 + 125 136 192 189 119 174 + 140 149 155 135 155 166 + 139 149 169 174 183 225 + 239 194 189 205 219 204 + 215 225 231 222 236 239 + 261 201 230 243 253 239 + 257 262 239 261 251 239 + 252 224 218 228 240 274 + 299 259 265 255 266 277 + 290 191 205 220 231 245 + 288 267 259 281 307 238 + 202 217 289 225 244 221 + 210 196 221 186 199 184 + 187 175 189 208 195 162 + 175 169 162 153 180 153 + 165 199 200 185 171 153 + 146 164 158 156 140 124 + 137 122 107 89 83 99 + 50 62 86 109 145 132 + 138 120 127 119 137 98 + 97 117 130 79 28 46 + 56 51 67 84 26 11 + 100000000 118 55 46 70 83 + 102 115 110 85 56 66 + 83 97 106 126 152 127 + 116 91 74 88 115 142 + 173 178 163 183 170 267 + 247 254 244 209 189 174 + 77 81 107 136 147 203 + 200 130 185 147 156 162 + 142 162 173 146 156 176 + 181 190 232 246 201 196 + 212 226 211 222 232 238 + 229 243 246 268 208 237 + 250 260 246 264 269 246 + 268 258 246 259 231 225 + 235 247 281 306 266 272 + 262 273 284 297 198 212 + 227 238 252 295 274 264 + 286 314 245 207 222 294 + 230 249 226 215 201 226 + 191 204 189 194 182 196 + 215 202 169 182 176 169 + 160 187 158 170 204 205 + 190 176 158 151 169 163 + 161 145 129 142 127 112 + 94 88 104 55 67 91 + 114 150 137 143 125 134 + 126 144 105 102 124 14 + 25 33 51 61 58 74 + 89 33 18 7 100000000 62 + 53 77 90 109 122 117 + 92 63 73 90 104 113 + 133 159 134 123 98 81 + 95 122 149 180 185 170 + 188 175 274 254 261 251 + 216 196 181 82 86 114 + 141 152 208 207 137 192 + 85 94 100 80 100 111 + 84 94 114 119 128 170 + 184 139 134 150 164 149 + 160 170 176 167 181 192 + 214 169 198 211 198 184 + 202 207 184 206 196 184 + 197 169 163 173 185 219 + 244 204 210 200 211 222 + 235 136 150 165 176 190 + 233 212 231 253 252 183 + 170 185 261 197 216 195 + 182 168 189 158 184 152 + 132 120 134 153 140 107 + 120 114 107 98 125 125 + 137 176 183 170 184 166 + 168 149 140 128 158 146 + 159 110 129 120 114 130 + 81 93 74 97 117 104 + 110 92 72 64 82 43 + 85 62 75 86 59 77 + 87 82 98 115 57 42 + 31 63 100000000 62 15 28 + 47 60 55 30 52 62 + 42 56 65 71 103 128 + 132 107 90 84 111 132 + 157 123 108 196 155 212 + 192 199 189 154 140 164 + 108 112 52 124 119 175 + 145 75 130 94 103 109 + 89 109 120 93 103 123 + 128 137 179 193 148 143 + 159 173 158 169 179 185 + 176 190 193 215 155 184 + 197 207 193 211 216 193 + 215 205 193 206 178 172 + 182 194 228 253 213 219 + 209 220 231 244 145 159 + 174 185 199 242 221 240 + 262 261 192 179 194 270 + 206 225 204 191 177 198 + 167 193 161 141 129 143 + 162 149 116 129 123 116 + 107 134 134 146 185 192 + 179 193 175 177 158 149 + 137 167 155 168 119 138 + 129 123 121 90 102 83 + 106 126 113 119 101 81 + 73 91 52 94 71 84 + 95 68 86 73 66 82 + 99 41 51 40 72 9 + 100000000 24 37 56 69 64 + 39 10 20 37 51 60 + 80 106 81 70 45 28 + 42 69 96 127 132 117 + 205 164 221 201 208 198 + 163 143 128 106 121 61 + 133 128 184 154 84 139 + 70 79 85 65 85 96 + 69 79 99 104 113 155 + 169 124 119 135 149 134 + 145 155 161 152 166 177 + 199 154 183 196 183 169 + 187 192 169 191 181 169 + 182 154 148 158 170 204 + 229 189 195 185 196 207 + 220 121 135 150 161 175 + 218 197 216 238 237 168 + 155 170 246 182 201 180 + 167 153 174 143 169 137 + 117 105 119 138 125 92 + 105 99 92 83 110 110 + 122 161 168 155 169 151 + 153 134 125 113 143 131 + 144 95 114 109 127 143 + 101 113 59 82 102 89 + 95 77 57 49 67 28 + 70 47 60 71 79 97 + 107 106 122 135 81 66 + 55 48 56 47 100000000 13 + 32 45 40 15 37 47 + 27 41 50 56 88 113 + 117 92 75 69 96 117 + 142 108 93 181 140 197 + 177 184 174 139 125 149 + 128 122 37 109 104 160 + 130 60 115 57 66 72 + 52 72 83 71 81 101 + 91 100 142 156 126 121 + 137 151 136 147 148 157 + 154 168 179 201 156 185 + 198 185 171 189 189 171 + 178 168 156 169 141 135 + 145 157 191 216 176 182 + 172 183 194 207 108 122 + 137 148 162 205 184 203 + 225 224 155 142 157 233 + 169 188 167 154 140 161 + 130 156 124 104 92 106 + 125 112 79 92 86 79 + 70 97 97 109 148 155 + 142 156 138 140 121 112 + 100 130 118 131 82 101 + 96 114 130 88 100 46 + 69 89 76 82 64 44 + 36 54 15 57 34 47 + 58 66 84 94 93 109 + 122 68 53 42 35 97 + 88 48 100000000 19 32 42 + 63 85 95 75 89 98 + 58 90 115 126 133 116 + 117 144 119 144 110 95 + 168 127 184 164 171 174 + 141 127 151 115 109 24 + 96 91 147 117 47 102 + 38 47 53 33 53 64 + 52 62 82 72 81 123 + 137 107 102 118 132 117 + 128 129 138 135 149 160 + 182 137 166 179 166 152 + 170 170 152 159 149 137 + 150 122 116 126 138 172 + 197 157 163 153 164 175 + 188 89 103 118 129 143 + 186 165 184 206 205 136 + 123 138 214 150 169 148 + 135 121 142 111 137 105 + 85 73 87 106 93 60 + 73 67 60 51 78 78 + 90 129 136 123 137 119 + 126 102 93 81 111 127 + 124 91 110 105 123 139 + 127 139 85 78 70 57 + 63 45 25 17 35 54 + 68 73 86 97 105 123 + 133 132 148 161 107 92 + 81 74 136 127 87 45 + 100000000 13 23 102 124 134 + 114 128 119 39 71 96 + 107 172 155 113 127 100 + 125 91 76 149 108 165 + 145 152 155 122 108 132 + 154 118 63 105 72 128 + 98 28 83 44 53 59 + 39 59 70 39 49 69 + 78 87 129 143 94 89 + 105 119 104 115 125 131 + 122 136 147 169 124 153 + 166 153 139 157 162 139 + 165 155 143 156 128 122 + 132 144 178 203 163 169 + 159 170 181 194 95 109 + 124 135 149 192 171 190 + 212 211 142 129 144 220 + 156 175 154 141 127 148 + 117 143 111 91 79 93 + 112 99 66 79 73 66 + 57 84 84 96 135 142 + 129 143 125 132 108 99 + 87 117 133 130 97 116 + 111 129 145 120 132 78 + 84 76 63 69 51 31 + 23 41 47 74 66 79 + 90 98 116 126 125 141 + 154 100 85 74 67 129 + 120 80 32 48 100000000 10 + 95 117 122 107 121 106 + 26 58 83 94 165 148 + 100 114 87 112 78 63 + 155 114 171 151 158 144 + 109 95 119 147 124 56 + 111 78 134 104 15 89 + 79 88 94 74 94 105 + 29 39 59 75 84 148 + 162 84 79 95 109 94 + 105 115 121 112 126 137 + 159 114 143 156 143 129 + 147 152 129 163 184 178 + 147 146 157 167 179 193 + 218 198 204 194 205 216 + 229 130 144 159 170 184 + 227 206 225 247 246 177 + 164 179 255 191 210 189 + 176 162 183 152 178 146 + 126 114 112 131 96 101 + 114 108 101 92 119 119 + 131 170 177 164 178 160 + 162 143 134 122 152 140 + 153 104 123 118 136 152 + 110 122 68 91 111 98 + 104 86 66 58 76 37 + 79 56 69 80 88 106 + 116 115 131 144 90 75 + 64 57 119 110 70 22 + 41 54 100000000 85 107 112 + 97 111 96 16 48 73 + 84 155 138 90 104 77 + 102 68 53 190 149 205 + 186 164 134 99 85 109 + 137 131 46 118 113 169 + 139 69 124 104 113 119 + 99 119 130 54 64 84 + 100 109 173 187 109 104 + 120 134 119 130 140 146 + 137 151 162 184 139 168 + 181 168 154 172 177 154 + 188 209 203 172 171 182 + 192 204 218 243 223 229 + 219 230 241 254 155 169 + 184 195 209 252 231 250 + 272 271 202 189 204 280 + 216 235 214 201 187 208 + 177 203 171 151 139 137 + 156 121 126 139 133 126 + 117 144 144 156 195 202 + 189 203 185 187 168 159 + 147 177 165 178 129 148 + 143 155 153 122 134 93 + 116 136 123 129 111 91 + 83 101 62 104 81 94 + 105 100 118 105 98 114 + 131 73 83 72 82 41 + 32 56 47 66 79 25 + 100000000 22 32 12 26 35 + 41 73 98 102 77 60 + 54 81 102 127 93 78 + 215 174 230 211 189 159 + 124 110 134 138 153 71 + 143 138 194 164 94 149 + 104 113 119 99 119 130 + 93 103 123 138 147 189 + 203 148 143 159 173 158 + 169 179 185 176 190 183 + 205 145 174 187 200 193 + 211 216 193 225 215 203 + 211 188 182 192 204 238 + 263 223 229 219 230 241 + 254 155 169 184 195 209 + 252 231 250 272 271 202 + 189 204 280 216 235 214 + 201 187 208 177 203 171 + 151 139 153 172 159 126 + 139 133 126 117 144 144 + 156 195 202 189 203 185 + 187 168 159 147 177 165 + 178 129 148 139 133 131 + 100 112 93 116 136 123 + 129 111 91 83 101 62 + 104 81 94 105 78 96 + 83 76 92 109 51 61 + 50 82 19 10 34 47 + 66 79 64 39 100000000 10 + 27 41 50 75 112 91 + 80 55 38 32 59 86 + 117 132 117 215 174 231 + 211 218 198 163 133 118 + 116 131 71 143 138 194 + 164 94 149 114 123 129 + 109 129 140 83 93 113 + 129 138 199 213 138 133 + 149 163 148 159 169 175 + 166 180 173 195 135 164 + 177 190 183 201 206 183 + 217 225 213 201 198 192 + 202 214 247 272 233 239 + 229 240 251 264 165 179 + 194 205 219 262 241 260 + 282 281 212 199 214 290 + 226 245 224 211 197 218 + 187 213 181 161 149 163 + 182 150 136 149 143 136 + 127 154 154 166 205 212 + 199 213 195 197 178 169 + 157 187 175 188 139 158 + 149 143 141 110 122 103 + 126 146 133 139 121 101 + 93 111 72 114 91 104 + 115 88 106 93 86 102 + 119 61 71 60 92 29 + 20 44 57 76 89 54 + 29 10 100000000 17 31 40 + 65 102 89 78 65 48 + 22 49 76 107 122 107 + 225 184 241 221 218 188 + 153 123 108 126 141 81 + 153 148 204 174 104 159 + 116 125 131 111 131 142 + 66 76 96 112 121 185 + 199 121 116 132 146 131 + 142 152 158 149 163 174 + 196 151 180 193 180 166 + 184 189 166 200 221 215 + 184 183 194 204 216 230 + 255 235 241 231 242 253 + 266 167 181 196 207 221 + 264 243 262 284 283 214 + 201 216 292 228 247 226 + 213 199 220 189 215 183 + 163 151 149 168 133 138 + 151 145 138 129 156 156 + 168 207 214 201 215 197 + 199 180 171 159 189 177 + 190 141 160 155 167 165 + 134 146 105 128 148 135 + 141 123 103 95 113 74 + 116 93 106 117 112 130 + 117 110 126 143 85 95 + 84 94 53 44 68 59 + 78 91 37 12 34 44 + 100000000 14 23 48 85 110 + 114 89 72 66 93 114 + 139 105 90 227 186 242 + 223 201 171 136 122 146 + 150 165 83 155 150 206 + 176 106 161 129 129 123 + 124 128 139 56 66 86 + 102 111 175 189 111 106 + 122 136 121 132 142 148 + 139 153 164 186 141 170 + 183 170 156 174 179 156 + 190 211 214 174 173 193 + 203 215 220 245 239 240 + 230 241 252 265 171 185 + 200 211 225 268 247 275 + 297 287 218 205 220 305 + 241 260 239 226 212 224 + 202 228 187 167 155 139 + 158 123 142 155 158 151 + 142 163 169 181 220 227 + 214 228 210 212 193 184 + 172 202 190 203 154 173 + 168 186 202 160 172 118 + 141 161 148 154 136 116 + 108 126 87 129 106 119 + 130 138 156 166 165 181 + 194 140 125 114 107 168 + 159 120 72 91 104 50 + 135 149 139 147 100000000 9 + 34 75 100 111 204 187 + 117 131 104 129 95 80 + 240 199 232 221 191 161 + 126 112 136 187 181 96 + 168 163 219 180 119 165 + 120 120 114 115 119 130 + 47 57 77 93 102 166 + 180 102 97 113 127 112 + 123 133 139 130 144 155 + 177 132 161 174 161 147 + 165 170 147 181 202 205 + 165 164 184 194 206 211 + 236 230 231 221 232 243 + 256 162 176 191 202 216 + 259 238 266 288 278 209 + 196 211 296 232 251 230 + 217 203 215 193 219 178 + 158 146 130 149 114 133 + 146 149 142 133 154 160 + 172 211 218 205 219 201 + 203 184 175 163 193 181 + 194 145 164 159 177 193 + 151 163 109 132 152 139 + 145 127 107 99 117 78 + 120 97 110 121 129 147 + 157 156 172 185 131 116 + 105 98 159 150 111 63 + 82 95 41 126 140 130 + 138 152 100000000 25 66 91 + 102 195 178 108 122 95 + 120 86 71 231 190 223 + 212 182 152 117 103 127 + 178 172 87 159 154 210 + 171 110 156 95 95 89 + 90 94 105 22 32 52 + 68 77 141 155 77 72 + 88 102 87 98 108 114 + 105 119 130 152 107 136 + 149 136 122 140 145 122 + 156 177 180 140 139 159 + 169 181 186 211 205 206 + 196 207 218 231 137 151 + 166 177 191 234 213 241 + 263 253 184 171 186 271 + 207 226 205 192 178 190 + 168 194 153 133 121 105 + 124 89 108 121 124 117 + 108 129 135 147 186 193 + 180 194 176 178 159 150 + 138 168 156 169 120 139 + 134 152 168 126 138 84 + 107 127 114 120 102 82 + 74 92 53 95 72 85 + 96 104 122 132 131 147 + 160 106 91 80 73 134 + 125 86 38 57 70 16 + 101 115 105 113 127 89 + 100000000 41 66 77 170 153 + 83 97 70 95 61 46 + 206 165 198 187 157 127 + 92 78 102 153 147 62 + 134 129 185 146 85 131 + 113 113 107 108 112 123 + 40 50 70 86 95 146 + 160 56 51 67 81 66 + 77 87 93 84 98 109 + 131 86 115 128 115 101 + 119 124 101 135 156 159 + 119 118 138 148 160 165 + 190 202 185 175 186 197 + 210 151 165 180 191 205 + 231 210 250 263 250 198 + 189 204 271 225 244 223 + 210 196 208 186 212 171 + 151 139 123 129 107 126 + 139 142 135 126 147 153 + 165 204 211 198 212 194 + 196 177 168 156 186 174 + 187 138 157 152 170 186 + 144 156 102 125 145 132 + 138 120 100 92 110 71 + 113 90 103 114 122 140 + 150 149 165 178 124 109 + 98 91 93 84 104 56 + 75 88 34 93 74 64 + 81 95 48 18 100000000 25 + 36 129 112 42 56 29 + 60 29 14 224 183 177 + 166 136 106 71 46 61 + 171 165 80 152 147 203 + 164 103 149 138 138 132 + 133 137 148 65 75 95 + 111 120 171 185 81 76 + 92 106 91 102 112 118 + 109 123 134 156 111 140 + 153 140 126 144 149 126 + 160 181 184 144 143 163 + 173 185 190 215 227 210 + 200 211 222 235 176 190 + 205 216 230 256 235 275 + 288 275 223 214 229 296 + 250 269 248 235 221 233 + 211 237 196 176 164 148 + 154 132 151 164 167 160 + 151 172 178 190 229 236 + 223 237 219 221 202 193 + 181 211 199 212 163 182 + 177 182 180 149 161 127 + 150 170 157 163 145 125 + 117 135 96 138 115 128 + 139 127 145 132 125 141 + 158 100 110 99 116 68 + 59 83 81 100 113 59 + 68 49 39 56 70 23 + 43 25 100000000 11 104 87 + 17 44 54 85 54 39 + 249 208 202 191 161 131 + 96 71 86 165 180 105 + 177 172 228 189 128 174 + 132 132 126 127 131 142 + 59 69 89 105 114 178 + 192 92 87 103 117 102 + 113 123 129 120 134 145 + 167 122 151 164 151 137 + 155 160 137 171 192 195 + 155 154 174 184 196 201 + 226 238 221 211 222 233 + 246 174 188 203 214 228 + 267 246 278 299 286 221 + 208 223 307 244 263 242 + 229 215 227 205 231 190 + 170 158 142 161 126 145 + 158 161 154 145 166 172 + 184 223 230 217 231 213 + 215 196 187 175 205 193 + 206 157 176 171 189 191 + 160 172 121 144 164 151 + 157 139 119 111 129 90 + 132 109 122 133 138 156 + 143 136 152 169 111 121 + 110 110 79 70 94 75 + 94 107 53 79 60 50 + 67 81 12 37 36 11 + 100000000 115 98 28 55 65 + 96 65 50 243 202 213 + 202 172 142 107 82 97 + 176 184 99 171 166 222 + 183 122 168 157 157 151 + 152 156 167 84 94 114 + 130 139 203 217 117 112 + 128 142 127 138 148 154 + 145 159 170 192 147 176 + 189 176 162 180 185 162 + 196 217 220 180 179 199 + 209 221 226 251 263 246 + 236 247 258 271 199 213 + 228 239 253 292 271 303 + 324 311 246 233 248 332 + 269 288 267 254 240 252 + 230 256 215 195 183 167 + 186 151 170 183 186 179 + 170 191 197 209 248 255 + 242 256 238 240 221 212 + 200 230 218 231 182 201 + 196 214 216 185 197 146 + 169 189 176 182 164 144 + 136 154 115 157 134 147 + 158 163 181 168 161 177 + 194 136 146 135 135 104 + 95 119 100 119 132 78 + 104 85 75 92 106 37 + 62 61 36 25 100000000 123 + 53 80 90 121 90 75 + 268 227 238 227 197 167 + 132 107 122 201 209 124 + 196 191 247 208 147 193 + 174 174 168 169 173 184 + 101 111 131 147 156 220 + 234 134 129 145 159 144 + 155 165 171 162 176 187 + 209 164 193 206 193 179 + 197 202 179 213 234 237 + 197 196 216 226 238 243 + 268 280 263 253 264 275 + 288 216 230 245 256 270 + 309 288 320 341 328 263 + 250 265 349 286 305 284 + 271 257 269 247 273 232 + 212 200 184 203 168 187 + 200 203 196 187 208 214 + 226 265 272 259 273 255 + 257 238 229 217 247 235 + 248 199 218 213 231 233 + 202 214 163 186 206 193 + 199 181 161 153 171 132 + 174 151 164 175 180 198 + 185 178 194 211 153 163 + 152 152 121 112 136 117 + 136 149 95 121 102 92 + 109 123 54 79 78 53 + 42 17 100000000 70 97 107 + 138 107 92 285 244 255 + 244 214 184 149 124 139 + 218 226 141 213 208 264 + 225 164 210 136 145 151 + 131 151 162 105 115 135 + 151 160 221 235 143 138 + 154 168 153 164 174 180 + 171 162 151 173 113 142 + 155 168 182 183 200 188 + 211 232 235 206 205 214 + 224 236 241 266 255 261 + 251 262 273 286 187 201 + 216 227 241 284 263 282 + 304 303 234 221 236 312 + 248 267 246 233 219 240 + 209 235 203 183 171 185 + 204 172 158 171 165 158 + 149 176 176 188 227 234 + 221 235 217 219 200 191 + 179 209 197 210 161 180 + 171 165 163 132 144 125 + 148 168 155 161 143 123 + 115 133 94 136 113 126 + 137 110 128 115 108 124 + 141 83 93 82 114 51 + 42 66 79 98 111 76 + 51 32 22 39 53 62 + 87 92 67 56 87 70 + 100000000 27 54 85 116 101 + 247 206 253 242 223 193 + 158 101 86 148 163 103 + 175 170 226 196 126 181 + 161 161 155 156 160 171 + 88 98 118 134 143 206 + 220 116 111 127 141 126 + 137 147 153 144 135 124 + 146 86 115 128 141 155 + 156 173 161 184 205 217 + 179 178 198 208 220 214 + 239 262 245 235 246 257 + 270 203 217 232 243 257 + 291 270 307 323 310 250 + 237 252 331 273 292 271 + 258 244 256 234 260 219 + 199 187 171 189 155 174 + 187 190 183 174 195 201 + 213 252 259 246 260 242 + 244 225 216 204 234 222 + 235 186 205 198 192 190 + 159 171 150 173 193 180 + 186 168 148 140 158 119 + 161 138 151 162 137 155 + 142 135 151 168 110 120 + 109 139 78 69 93 104 + 123 136 82 78 59 49 + 66 80 41 66 65 40 + 29 114 97 27 100000000 27 + 58 89 74 272 231 226 + 215 196 166 131 74 59 + 175 190 128 200 195 251 + 212 151 197 155 146 140 + 160 145 156 101 83 103 + 119 128 179 193 89 84 + 100 114 99 110 120 126 + 117 108 97 119 59 88 + 101 114 128 129 146 134 + 157 178 190 152 151 171 + 181 193 187 212 235 218 + 208 219 230 243 184 198 + 213 224 238 264 243 283 + 296 283 231 222 237 304 + 271 290 269 256 254 241 + 247 273 204 184 172 156 + 162 140 159 172 184 177 + 168 180 214 226 265 272 + 259 273 255 257 238 229 + 217 247 235 248 199 218 + 213 219 217 186 198 163 + 186 206 193 199 181 161 + 153 171 132 174 151 164 + 175 164 182 169 162 178 + 195 137 147 136 152 105 + 96 120 117 136 149 95 + 105 86 76 93 107 68 + 79 61 67 56 141 124 + 54 27 100000000 31 62 47 + 285 244 199 188 169 139 + 104 47 32 202 217 141 + 213 208 261 197 164 182 + 127 118 112 132 117 128 + 102 55 75 91 100 151 + 165 61 56 72 86 71 + 82 92 98 89 77 66 + 88 28 57 70 83 97 + 98 115 106 126 147 159 + 124 123 143 153 164 156 + 181 206 189 179 190 201 + 214 156 170 185 196 210 + 235 214 254 267 254 203 + 194 209 275 243 262 241 + 228 226 213 236 249 176 + 156 144 128 134 112 131 + 144 156 149 140 152 209 + 221 254 261 254 268 250 + 257 233 224 212 242 236 + 249 200 219 214 232 248 + 206 218 164 187 201 188 + 194 176 156 148 166 133 + 175 152 165 176 184 202 + 200 193 209 226 168 171 + 160 153 136 127 151 118 + 137 145 96 136 117 107 + 124 138 99 80 62 87 + 87 172 155 85 58 31 + 100000000 34 48 280 239 168 + 157 141 111 76 17 33 + 233 227 142 214 203 233 + 169 146 154 93 84 78 + 98 83 94 69 21 41 + 57 66 117 131 27 22 + 38 52 37 48 58 64 + 55 69 80 102 57 86 + 99 86 72 90 95 72 + 106 127 130 90 89 109 + 119 131 136 161 173 156 + 146 157 168 181 122 136 + 151 162 176 202 181 221 + 234 221 169 160 175 242 + 209 228 207 194 192 179 + 202 215 142 122 110 94 + 100 78 97 110 122 115 + 106 118 175 187 220 227 + 220 234 216 223 199 190 + 178 208 203 216 167 186 + 181 199 215 173 185 131 + 154 167 154 160 142 122 + 114 132 100 142 119 132 + 143 151 169 179 178 194 + 207 153 138 127 120 122 + 113 133 85 104 111 63 + 122 103 93 110 124 77 + 47 29 54 65 158 141 + 71 85 58 34 100000000 15 + 246 205 148 137 107 77 + 42 17 67 200 194 109 + 181 169 199 135 112 120 + 108 99 93 113 98 109 + 54 36 56 72 81 132 + 146 42 37 53 67 52 + 63 73 79 70 84 95 + 117 72 101 114 101 87 + 105 110 87 121 142 145 + 105 104 124 134 146 151 + 176 188 171 161 172 183 + 196 137 151 166 177 191 + 217 196 236 249 236 184 + 175 190 257 224 243 222 + 209 207 194 200 226 157 + 137 125 109 115 93 112 + 125 137 130 121 133 167 + 179 218 225 212 226 208 + 210 191 182 170 200 188 + 201 152 171 166 184 200 + 158 170 116 139 159 146 + 152 134 114 106 124 85 + 127 104 117 128 136 154 + 164 163 179 192 138 123 + 112 105 107 98 118 70 + 89 102 48 107 88 78 + 95 109 62 32 14 39 + 50 143 126 56 70 43 + 49 15 100000000 238 197 163 + 152 122 92 57 32 75 + 185 179 94 166 161 214 + 150 117 135 155 146 152 + 172 192 203 220 208 228 + 211 175 165 179 193 248 + 232 203 189 183 171 162 + 171 185 196 218 229 205 + 215 202 188 202 185 184 + 174 164 152 165 137 131 + 141 153 187 191 144 164 + 168 151 162 175 104 90 + 105 116 130 173 152 114 + 136 192 123 75 90 144 + 80 99 78 65 51 94 + 41 26 57 134 120 134 + 148 187 133 146 165 172 + 168 154 42 38 26 27 + 12 48 30 37 43 34 + 44 52 93 65 75 76 + 89 107 113 121 133 106 + 86 78 74 62 140 153 + 176 194 142 117 161 174 + 150 158 176 148 155 152 + 135 180 180 169 162 224 + 215 175 188 201 214 215 + 190 212 222 202 216 225 + 231 239 264 275 260 243 + 244 271 268 257 259 244 + 100000000 19 180 160 167 179 + 236 274 290 142 102 151 + 89 53 58 125 221 110 + 196 187 193 213 233 244 + 245 249 269 252 216 206 + 220 234 289 273 244 230 + 224 212 203 212 226 237 + 259 270 246 256 243 229 + 243 226 225 215 205 193 + 206 178 172 182 194 228 + 205 185 205 209 192 203 + 216 145 131 146 157 171 + 187 166 126 148 206 164 + 116 131 156 121 111 79 + 106 92 135 82 67 98 + 175 161 175 189 228 174 + 187 206 213 209 195 83 + 79 67 68 53 29 11 + 18 36 71 83 53 74 + 66 76 57 90 108 94 + 122 134 107 87 79 113 + 101 141 154 217 235 143 + 118 162 175 151 159 177 + 146 149 133 116 174 181 + 170 163 224 215 176 189 + 208 221 216 191 213 223 + 203 217 226 232 264 289 + 285 260 243 245 272 293 + 298 284 269 41 100000000 221 + 201 208 220 277 301 325 + 123 103 152 90 92 99 + 166 236 151 141 132 138 + 158 178 189 206 194 214 + 197 107 97 111 125 224 + 143 125 111 115 103 94 + 93 107 107 129 140 111 + 98 85 99 70 53 76 + 42 30 42 55 69 49 + 39 27 12 37 69 52 + 42 53 64 77 90 104 + 88 80 94 97 76 116 + 129 116 106 118 133 137 + 162 131 163 152 150 137 + 160 173 140 120 106 120 + 80 119 119 132 151 158 + 154 140 200 190 178 185 + 187 213 231 238 218 209 + 202 227 272 240 236 255 + 250 268 284 272 284 230 + 223 215 202 208 190 170 + 162 180 199 213 218 231 + 242 250 268 278 277 293 + 306 252 237 226 219 281 + 272 232 232 187 200 210 + 247 269 275 259 273 267 + 226 225 250 255 317 300 + 253 226 199 168 202 216 + 225 224 100000000 20 57 81 + 147 185 201 299 263 208 + 250 211 157 111 207 96 + 121 112 118 138 158 169 + 186 174 194 177 87 77 + 91 105 213 132 114 100 + 95 83 74 82 96 96 + 118 129 100 87 74 88 + 59 42 65 31 10 22 + 35 49 29 19 7 32 + 57 49 32 22 33 44 + 57 70 84 68 60 74 + 78 57 97 110 97 86 + 98 113 118 143 112 144 + 132 130 117 140 153 120 + 100 86 100 60 99 99 + 112 131 138 134 120 180 + 170 158 165 167 194 212 + 219 198 189 182 207 252 + 220 216 235 230 248 264 + 252 264 210 203 195 182 + 188 170 150 142 160 179 + 193 198 211 222 230 248 + 258 257 273 286 232 217 + 206 199 261 252 212 212 + 167 180 190 227 249 259 + 239 253 253 206 205 230 + 241 297 280 242 215 188 + 157 191 205 206 204 20 + 100000000 37 70 136 174 190 + 279 243 188 230 191 137 + 91 187 76 159 150 156 + 176 196 207 224 188 208 + 215 120 110 124 128 189 + 108 90 76 87 97 67 + 58 72 72 94 105 76 + 63 50 64 35 18 41 + 7 28 40 53 82 67 + 57 45 37 62 87 70 + 60 71 82 95 108 122 + 106 98 112 116 95 135 + 148 135 124 136 151 156 + 181 150 182 170 168 155 + 178 191 158 138 124 138 + 93 132 137 150 169 176 + 172 158 218 208 196 203 + 205 232 250 257 236 227 + 220 245 290 258 254 273 + 268 286 302 290 302 248 + 241 233 220 226 208 188 + 180 198 217 231 236 249 + 260 268 286 296 295 311 + 324 270 255 244 237 269 + 260 250 250 205 218 228 + 265 250 240 257 271 232 + 213 195 220 220 305 288 + 218 191 164 133 167 181 + 244 242 49 38 100000000 46 + 112 150 166 317 281 226 + 268 229 175 129 225 114 + 126 117 123 143 163 174 + 191 163 183 182 80 70 + 84 98 164 83 54 40 + 51 61 31 22 36 47 + 69 80 56 66 53 39 + 45 28 5 37 58 70 + 13 42 62 72 75 67 + 92 117 100 90 101 112 + 125 75 89 104 115 129 + 146 125 165 178 165 122 + 134 149 186 183 180 181 + 168 166 153 176 189 125 + 105 91 105 53 92 104 + 117 136 143 139 125 208 + 206 194 201 203 231 249 + 256 232 223 211 241 257 + 254 221 240 235 253 269 + 257 269 215 208 200 187 + 193 175 155 147 165 184 + 198 203 216 227 235 253 + 263 262 278 291 237 222 + 211 204 244 235 217 217 + 172 185 195 232 225 215 + 232 246 207 188 170 195 + 195 280 263 193 166 139 + 108 142 156 243 238 79 + 68 30 100000000 87 125 141 + 284 248 193 235 202 173 + 96 192 81 160 151 157 + 177 197 208 225 183 203 + 216 114 104 118 16 184 + 103 10 24 35 45 51 + 42 56 67 89 100 76 + 86 73 59 77 82 59 + 93 114 117 77 76 96 + 106 118 123 148 160 143 + 133 144 155 168 109 123 + 138 149 163 189 168 208 + 221 208 156 168 183 229 + 217 223 215 202 200 187 + 210 223 159 139 125 139 + 87 126 138 151 170 177 + 173 159 242 240 228 235 + 237 265 283 290 266 257 + 245 275 291 288 255 274 + 269 287 303 291 303 249 + 242 234 221 227 209 189 + 181 199 218 232 237 250 + 261 269 287 297 296 312 + 325 271 256 245 238 264 + 255 251 246 206 219 224 + 264 245 235 252 266 227 + 208 190 215 215 300 283 + 213 186 159 128 162 176 + 277 272 135 124 94 64 + 100000000 145 161 318 282 227 + 269 236 207 130 226 115 + 110 101 95 115 100 111 + 86 38 58 74 83 134 + 148 44 39 55 69 54 + 65 75 81 72 86 83 + 105 45 74 87 100 89 + 107 112 89 123 144 147 + 107 106 126 136 148 153 + 178 190 173 163 174 185 + 198 139 153 168 179 193 + 219 198 238 251 238 186 + 177 192 259 226 245 224 + 211 209 196 219 232 159 + 139 127 111 117 95 114 + 127 139 132 123 135 192 + 204 237 244 237 251 233 + 240 216 207 195 225 220 + 233 184 203 198 216 232 + 190 202 148 171 184 171 + 177 159 139 131 149 117 + 159 136 149 160 168 186 + 196 195 211 224 170 155 + 144 137 139 130 150 102 + 121 128 80 139 120 110 + 127 141 94 64 46 71 + 82 175 158 88 75 48 + 17 17 32 263 222 165 + 154 124 94 59 100000000 50 + 217 211 126 198 186 216 + 152 129 137 123 114 108 + 128 113 124 69 51 71 + 87 96 147 161 57 52 + 68 82 67 78 88 94 + 85 99 98 120 60 89 + 102 115 102 120 125 102 + 136 157 160 120 119 139 + 149 161 166 191 203 186 + 176 187 198 211 152 166 + 181 192 206 232 211 251 + 264 251 199 190 205 272 + 239 258 237 224 222 209 + 215 241 172 152 140 124 + 130 108 127 140 152 145 + 136 148 182 194 233 240 + 227 241 223 225 206 197 + 185 215 203 216 167 186 + 181 199 215 173 185 131 + 154 174 161 167 149 129 + 121 139 100 142 119 132 + 143 151 169 179 178 194 + 207 153 138 127 120 122 + 113 133 85 104 117 63 + 122 103 93 110 124 77 + 47 29 54 65 158 141 + 71 85 58 32 30 15 + 253 212 178 167 137 107 + 72 15 100000000 200 194 109 + 181 176 229 165 132 150 + 190 199 205 185 205 216 + 189 199 219 224 233 269 + 283 244 239 255 269 254 + 265 275 266 272 286 289 + 311 251 280 293 303 289 + 306 289 288 278 268 256 + 269 241 235 245 257 291 + 295 248 268 272 255 266 + 279 208 194 209 220 234 + 277 256 227 249 296 227 + 179 194 257 202 212 180 + 187 173 198 163 158 161 + 237 224 238 252 245 212 + 225 219 212 203 230 130 + 142 158 159 144 130 112 + 105 123 117 129 99 83 + 96 99 66 66 45 29 + 27 39 63 86 122 109 + 115 97 110 169 187 99 + 74 118 131 56 64 82 + 23 30 24 7 55 137 + 126 119 105 96 120 133 + 152 165 160 135 106 116 + 133 147 156 176 202 177 + 166 141 124 138 165 192 + 223 228 213 142 129 284 + 264 271 283 259 239 224 + 100000000 58 108 113 124 180 + 229 180 214 215 224 230 + 210 230 241 214 224 244 + 249 258 257 271 269 264 + 280 294 279 275 263 254 + 263 277 288 310 295 297 + 307 294 280 294 277 276 + 266 256 244 257 229 223 + 233 245 279 266 236 256 + 260 243 254 267 196 182 + 197 208 222 248 227 187 + 209 267 215 167 182 217 + 172 172 140 157 143 186 + 133 118 149 226 212 226 + 240 270 225 238 244 237 + 228 246 122 130 118 119 + 104 90 72 65 83 77 + 89 59 43 56 66 26 + 8 26 42 40 52 76 + 93 85 119 107 110 123 + 194 212 112 87 131 144 + 69 77 95 67 74 81 + 64 99 150 139 132 149 + 140 145 158 177 190 185 + 160 150 160 172 186 195 + 201 233 221 210 185 168 + 182 209 236 267 253 238 + 102 89 272 252 259 271 + 284 270 268 67 100000000 121 + 80 98 150 217 205 202 + 94 103 109 89 109 120 + 93 103 123 128 137 179 + 193 148 143 159 173 158 + 169 179 185 176 190 201 + 223 178 207 220 207 193 + 211 216 193 215 205 193 + 206 178 172 182 194 228 + 253 213 219 209 220 231 + 244 145 159 174 185 199 + 242 221 240 262 261 192 + 179 194 270 206 225 204 + 191 177 198 167 193 161 + 141 129 143 162 149 116 + 129 123 116 107 134 134 + 146 185 192 179 187 169 + 162 158 149 137 156 140 + 153 119 123 105 99 115 + 66 78 83 106 126 113 + 119 101 81 73 91 52 + 94 71 25 36 44 62 + 72 69 85 100 44 29 + 18 11 73 64 24 37 + 56 69 64 39 61 71 + 51 65 74 80 112 137 + 134 109 92 93 120 141 + 166 132 117 199 164 221 + 201 208 198 163 149 173 + 93 97 100000000 133 128 184 + 154 84 139 156 165 171 + 151 171 182 155 165 185 + 190 199 223 237 210 205 + 221 235 220 231 229 220 + 229 243 254 276 240 263 + 273 260 246 260 243 242 + 232 222 210 223 195 189 + 199 211 245 249 202 222 + 226 209 220 233 162 148 + 163 174 188 231 210 190 + 212 250 181 133 148 220 + 156 175 153 141 127 152 + 117 131 115 192 178 192 + 206 211 178 191 185 178 + 169 196 84 96 131 132 + 117 103 85 78 96 90 + 87 72 56 69 53 39 + 21 39 55 53 65 17 + 40 76 63 69 51 64 + 135 153 53 28 72 85 + 82 90 108 80 87 94 + 77 106 91 80 73 135 + 126 86 99 118 131 126 + 101 123 133 113 127 136 + 142 174 199 196 171 154 + 155 182 203 228 194 179 + 115 102 238 218 225 237 + 225 211 235 80 13 62 + 100000000 78 134 183 146 168 + 153 144 150 170 190 201 + 218 206 226 209 173 163 + 177 191 246 230 201 187 + 181 169 160 169 183 194 + 216 227 203 213 200 186 + 200 183 182 172 162 150 + 163 135 129 139 151 185 + 189 142 162 166 149 160 + 173 102 88 103 114 128 + 171 150 130 152 190 121 + 73 88 160 96 115 94 + 81 67 92 57 65 55 + 132 118 132 146 185 131 + 144 163 170 166 152 24 + 36 65 66 51 65 47 + 54 30 21 9 39 91 + 52 55 74 69 87 103 + 101 113 86 42 34 21 + 9 120 133 174 192 122 + 97 141 154 130 138 156 + 128 135 142 125 160 160 + 149 142 204 195 155 168 + 187 200 195 170 192 202 + 182 196 205 211 237 262 + 265 240 223 224 251 266 + 255 257 242 77 36 178 + 158 165 177 234 272 288 + 128 82 131 69 100000000 74 + 123 215 108 173 164 170 + 190 210 221 238 226 246 + 229 193 183 197 211 266 + 250 221 207 201 189 180 + 189 203 214 236 247 223 + 233 220 206 220 203 202 + 192 182 170 183 155 149 + 159 171 205 183 162 182 + 186 169 180 193 122 108 + 123 134 148 165 144 104 + 126 184 141 93 108 134 + 70 89 68 55 41 112 + 31 16 75 152 138 152 + 166 205 151 164 183 190 + 186 172 60 56 44 45 + 30 96 78 85 61 52 + 62 70 129 83 93 112 + 107 125 141 139 151 124 + 104 96 92 80 158 171 + 194 212 160 135 179 192 + 168 176 194 166 173 180 + 163 198 198 187 180 242 + 233 193 206 219 232 233 + 208 230 240 220 234 243 + 249 257 282 293 278 261 + 262 289 286 275 277 262 + 108 67 198 178 185 197 + 254 292 308 166 120 169 + 107 71 100000000 143 239 128 + 56 47 53 73 93 104 + 121 109 129 112 83 73 + 87 101 149 158 129 111 + 91 79 88 97 111 122 + 144 155 131 141 128 114 + 132 120 110 109 99 87 + 100 72 66 76 88 122 + 147 107 113 103 114 125 + 138 39 53 68 79 93 + 136 115 130 152 155 86 + 47 62 160 96 115 94 + 81 79 66 89 102 29 + 9 23 37 56 95 34 + 21 40 47 56 29 129 + 119 107 114 116 144 162 + 169 147 138 131 156 187 + 169 151 170 165 183 199 + 187 199 145 138 130 117 + 123 105 85 77 95 114 + 128 133 146 157 165 183 + 193 192 208 221 167 152 + 141 134 196 187 147 147 + 102 115 125 162 184 194 + 174 188 188 141 140 165 + 176 232 215 182 196 169 + 183 160 145 156 153 115 + 95 102 105 162 177 201 + 214 178 123 165 132 86 + 100000000 122 33 29 38 44 + 24 44 55 72 60 80 + 63 72 114 128 105 100 + 116 130 115 126 120 129 + 133 147 158 180 135 164 + 177 164 150 168 161 150 + 150 140 128 141 113 107 + 117 129 163 188 148 154 + 144 155 166 179 80 94 + 109 120 134 177 156 175 + 197 196 127 114 129 205 + 141 160 139 126 112 133 + 102 128 96 76 64 78 + 97 84 51 64 58 51 + 42 69 69 81 120 127 + 114 128 110 117 93 84 + 72 102 118 115 82 101 + 96 114 130 118 130 76 + 69 61 48 54 36 16 + 8 26 45 59 64 77 + 88 96 114 124 123 139 + 152 98 83 72 65 127 + 118 78 78 33 46 56 + 93 115 125 105 119 128 + 72 91 116 127 163 146 + 133 147 120 145 111 96 + 140 99 156 136 143 146 + 120 128 152 145 109 54 + 96 63 119 89 100000000 74 + 45 36 42 62 82 93 + 110 98 118 101 70 60 + 74 88 138 134 105 91 + 78 66 64 73 87 98 + 120 131 107 117 104 90 + 104 87 86 76 66 54 + 67 39 33 43 55 89 + 114 74 80 70 81 92 + 105 6 20 35 46 60 + 103 82 122 135 122 53 + 62 77 143 111 130 109 + 96 94 81 104 117 44 + 24 10 24 43 82 23 + 36 55 62 58 44 127 + 134 122 129 131 159 168 + 175 151 142 130 160 176 + 173 140 159 154 172 188 + 176 188 134 127 119 106 + 112 94 74 66 84 103 + 117 122 135 146 154 172 + 182 181 197 210 156 141 + 130 123 185 176 136 136 + 91 104 114 151 173 183 + 163 177 177 130 129 154 + 165 221 204 171 185 158 + 159 149 134 171 157 82 + 62 69 81 138 166 190 + 203 167 112 154 121 101 + 15 111 100000000 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv70.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv70.atsp new file mode 100644 index 0000000..a966e49 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ftv70.atsp @@ -0,0 +1,849 @@ +NAME: ftv70 +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 71 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 100000000 26 46 74 82 65 + 90 104 102 100 147 134 + 90 75 69 106 117 42 + 71 96 158 89 76 125 + 38 40 58 59 13 38 + 31 22 103 143 106 94 + 137 104 123 140 98 70 + 58 38 30 48 67 118 + 120 105 149 140 100 55 + 115 141 94 93 122 113 + 162 154 76 118 36 21 + 62 165 92 94 66 66 + 100000000 20 48 56 39 126 + 81 76 109 156 140 156 + 141 135 172 183 108 137 + 162 224 155 142 190 104 + 76 124 95 79 104 97 + 88 130 176 133 121 164 + 131 150 167 125 97 85 + 65 57 75 94 145 147 + 132 160 151 80 82 142 + 162 74 67 96 87 189 + 128 103 145 102 66 128 + 176 119 121 40 46 53 + 100000000 28 36 19 106 61 + 56 89 136 120 136 121 + 115 152 163 88 117 142 + 204 135 122 170 84 56 + 104 75 59 84 77 68 + 110 156 113 101 144 111 + 130 147 105 77 65 45 + 37 55 74 125 127 112 + 140 131 60 62 122 142 + 54 47 76 67 169 108 + 83 125 82 46 108 156 + 99 101 20 73 87 72 + 100000000 30 46 133 55 50 + 83 130 114 158 117 137 + 174 185 115 144 169 231 + 162 149 198 111 83 131 + 102 86 111 104 95 176 + 216 179 167 210 176 195 + 182 140 143 131 111 103 + 121 109 160 162 147 131 + 122 94 113 131 133 56 + 38 67 39 235 99 118 + 190 109 94 135 147 162 + 167 70 43 57 42 70 + 100000000 16 103 25 20 53 + 100 84 128 87 107 144 + 155 85 114 139 201 132 + 119 168 81 53 101 72 + 56 81 74 65 146 186 + 149 137 180 147 166 183 + 141 113 101 81 73 91 + 110 161 163 148 164 155 + 102 98 158 166 89 71 + 100 42 205 109 119 161 + 79 64 105 180 135 137 + 62 27 41 26 54 62 + 100000000 87 87 82 97 144 + 131 117 102 96 133 144 + 69 98 123 185 116 103 + 152 65 37 85 56 40 + 65 58 49 130 170 133 + 121 164 131 150 167 125 + 97 85 65 57 75 94 + 145 147 132 166 157 86 + 82 142 168 80 73 102 + 93 189 134 103 145 63 + 48 89 182 119 121 46 + 129 155 175 203 199 194 + 100000000 14 180 38 85 72 + 95 54 74 111 122 87 + 116 141 186 134 146 195 + 117 117 137 65 116 148 + 155 151 218 213 235 223 + 266 233 252 269 227 199 + 187 167 159 177 196 247 + 249 234 260 251 229 184 + 244 262 204 186 155 158 + 255 157 205 247 93 150 + 80 276 221 223 195 137 + 163 183 211 189 202 104 + 100000000 170 28 75 62 103 + 62 82 119 130 95 124 + 149 194 142 154 203 125 + 125 145 73 124 156 163 + 159 226 221 243 231 274 + 241 260 277 235 207 195 + 175 167 185 204 255 257 + 242 250 241 232 192 250 + 252 194 176 145 148 263 + 147 213 255 101 158 88 + 266 229 231 203 106 120 + 105 91 63 79 109 5 + 100000000 33 80 64 108 67 + 87 124 135 100 129 154 + 199 147 159 208 130 116 + 150 78 119 144 137 128 + 209 226 212 200 238 189 + 208 195 153 176 164 144 + 136 154 122 173 175 160 + 144 135 107 126 144 146 + 69 51 80 22 268 89 + 131 203 106 127 93 160 + 175 200 83 109 135 155 + 183 161 174 76 81 142 + 100000000 47 34 75 34 54 + 91 102 67 96 121 166 + 114 126 175 97 97 117 + 45 96 128 135 131 198 + 193 215 203 246 213 232 + 249 207 179 167 147 139 + 157 176 227 229 214 222 + 213 204 164 222 224 166 + 148 117 120 235 119 185 + 227 73 130 60 238 201 + 203 175 157 171 156 141 + 114 130 136 34 95 60 + 100000000 40 135 94 114 151 + 162 127 156 181 226 174 + 186 235 157 157 177 105 + 156 188 188 179 258 253 + 263 251 288 239 258 245 + 203 227 215 195 187 205 + 172 223 207 210 175 166 + 157 176 175 177 119 101 + 70 73 295 72 181 253 + 133 178 120 191 225 251 + 133 143 169 174 159 132 + 148 110 65 113 34 31 + 100000000 102 68 88 122 133 + 101 130 155 197 148 160 + 209 131 131 151 79 130 + 162 169 165 232 227 249 + 237 280 247 266 263 221 + 213 201 181 173 191 190 + 241 225 228 193 184 175 + 194 193 195 137 119 88 + 91 269 90 199 261 107 + 164 94 209 235 237 151 + 117 143 163 191 199 182 + 84 98 204 73 109 91 + 100000000 42 51 44 55 75 + 90 96 119 108 120 165 + 105 105 125 53 104 136 + 143 139 192 187 211 204 + 242 221 240 257 215 187 + 175 155 147 165 184 235 + 237 222 266 257 217 172 + 232 258 211 210 179 182 + 228 181 193 235 81 138 + 68 282 209 211 183 75 + 101 121 149 157 140 42 + 56 176 34 81 68 41 + 100000000 20 57 68 33 62 + 87 132 80 92 141 63 + 63 83 11 62 94 101 + 97 164 159 181 169 212 + 179 198 215 173 145 133 + 113 105 123 142 193 195 + 180 224 215 175 130 190 + 216 169 168 151 154 201 + 153 151 193 39 96 26 + 240 167 169 141 95 121 + 141 169 177 160 62 76 + 196 54 101 88 21 20 + 100000000 37 48 53 82 89 + 112 100 112 158 83 83 + 103 31 82 114 121 117 + 184 179 201 189 232 199 + 218 235 193 165 153 133 + 125 143 162 213 215 200 + 244 235 195 150 210 236 + 189 188 171 174 221 173 + 171 213 59 116 46 260 + 187 189 161 90 116 136 + 164 172 155 99 113 192 + 91 138 122 44 57 37 + 100000000 11 48 46 52 75 + 64 76 121 78 78 98 + 68 77 109 116 112 148 + 143 167 160 198 194 213 + 230 188 160 148 128 120 + 138 157 208 210 195 239 + 230 190 145 205 231 184 + 183 208 203 184 210 166 + 208 54 111 68 255 182 + 178 156 79 105 125 153 + 161 144 99 113 181 91 + 138 125 58 57 37 54 + 100000000 37 35 41 103 53 + 65 114 67 67 87 68 + 66 98 105 101 137 132 + 156 149 187 183 202 219 + 177 149 137 117 109 127 + 146 197 199 184 228 219 + 179 134 194 220 173 172 + 201 192 174 210 155 197 + 43 100 57 244 171 167 + 145 42 68 88 116 124 + 107 75 89 144 67 114 + 101 48 33 27 64 75 + 100000000 29 54 116 47 59 + 108 30 30 50 44 29 + 61 68 64 131 126 148 + 136 179 146 165 182 140 + 112 100 80 72 90 109 + 160 162 147 191 182 142 + 97 157 183 136 135 164 + 155 168 186 118 160 6 + 63 20 207 134 136 108 + 101 127 147 175 183 166 + 134 148 203 126 173 160 + 104 92 83 69 46 59 + 100000000 25 87 18 30 79 + 89 89 109 103 88 120 + 127 123 102 97 121 114 + 152 162 181 208 193 144 + 159 139 131 149 168 219 + 221 206 250 241 201 156 + 216 242 195 194 223 214 + 139 245 177 176 65 122 + 79 266 193 132 167 100 + 126 146 174 182 165 120 + 134 202 112 159 146 79 + 78 58 44 21 58 56 + 100000000 62 71 83 108 88 + 88 108 89 87 119 126 + 122 155 150 174 167 205 + 204 223 240 198 170 158 + 138 130 148 167 218 220 + 205 249 240 200 155 215 + 241 194 193 222 213 171 + 231 176 218 64 121 78 + 265 192 185 166 92 118 + 138 166 174 157 125 139 + 194 117 164 151 98 83 + 77 114 97 50 51 76 + 100000000 9 21 46 80 80 + 100 94 79 111 118 114 + 93 88 112 105 143 153 + 172 199 184 135 150 130 + 122 140 159 210 212 197 + 241 232 192 147 207 233 + 186 185 214 205 130 236 + 168 167 56 113 70 257 + 184 123 158 83 109 129 + 157 165 148 116 130 185 + 108 155 142 89 74 68 + 105 88 41 42 67 129 + 100000000 12 61 71 71 91 + 85 70 102 109 105 84 + 79 103 96 134 144 163 + 190 175 126 141 121 113 + 131 150 201 203 188 232 + 223 183 138 198 224 177 + 176 205 196 121 227 159 + 158 47 104 61 248 175 + 114 149 71 97 117 145 + 153 136 104 118 173 96 + 143 130 77 62 56 93 + 76 29 30 55 117 48 + 100000000 49 59 59 79 73 + 58 90 97 93 72 67 + 91 84 122 132 151 178 + 163 114 129 109 101 119 + 138 189 191 176 220 211 + 171 126 186 212 165 164 + 193 184 109 215 147 146 + 35 92 49 236 163 102 + 137 204 230 250 278 286 + 269 224 238 306 216 255 + 237 173 182 162 147 125 + 162 160 104 114 123 135 + 100000000 192 192 163 193 191 + 223 230 226 144 139 147 + 156 174 184 165 230 215 + 186 249 242 234 252 251 + 267 282 289 332 323 297 + 259 299 325 298 297 325 + 317 113 327 260 198 168 + 225 182 348 237 174 270 + 38 64 84 112 120 103 + 78 92 140 88 135 122 + 78 63 57 94 105 30 + 59 84 146 77 38 87 + 100000000 28 20 47 25 31 + 38 47 110 105 129 122 + 160 142 161 178 136 108 + 96 76 68 86 105 156 + 158 143 187 178 138 93 + 153 179 132 131 160 151 + 147 192 114 156 24 59 + 50 203 130 132 104 151 + 177 197 225 221 216 50 + 64 202 60 107 94 117 + 76 96 133 144 109 138 + 163 208 156 168 217 139 + 100000000 159 19 138 170 177 + 173 240 235 257 245 288 + 255 274 291 249 221 209 + 189 181 199 218 269 271 + 256 282 273 251 206 266 + 284 226 208 177 180 277 + 179 227 269 115 172 102 + 298 243 245 217 89 115 + 135 163 171 154 122 136 + 191 114 161 148 95 80 + 74 111 94 47 48 73 + 135 66 18 67 77 77 + 100000000 91 76 108 115 111 + 90 85 109 102 140 150 + 169 196 181 132 147 127 + 119 137 156 207 209 194 + 238 229 189 144 204 230 + 183 182 211 202 127 233 + 165 164 53 110 67 254 + 181 120 155 132 158 178 + 206 202 197 31 45 183 + 41 88 75 98 57 77 + 114 125 90 119 144 189 + 137 149 198 120 55 140 + 100000000 119 151 158 154 221 + 216 238 226 269 236 255 + 272 230 202 190 170 162 + 180 199 250 252 237 263 + 254 232 187 247 265 207 + 189 158 161 258 160 208 + 250 96 153 83 279 224 + 226 198 13 39 59 87 + 95 78 77 91 115 87 + 134 121 77 62 56 93 + 104 29 58 83 145 76 + 63 112 25 27 45 46 + 100000000 32 39 35 116 130 + 119 107 150 117 136 153 + 111 83 71 51 43 61 + 80 131 133 118 162 153 + 113 68 128 154 107 106 + 135 126 172 167 89 131 + 23 34 49 178 105 107 + 79 38 48 68 96 104 + 87 109 123 124 119 166 + 153 109 94 88 125 136 + 61 90 115 177 108 69 + 118 31 59 51 78 32 + 100000000 7 16 123 136 126 + 114 157 124 143 160 118 + 90 78 58 50 68 87 + 138 140 125 169 160 120 + 75 135 161 114 115 144 + 135 178 176 96 138 55 + 41 81 185 112 114 88 + 31 41 61 89 97 80 + 105 119 117 115 162 149 + 105 90 84 121 132 57 + 86 111 173 104 65 114 + 27 55 47 74 28 7 + 100000000 9 116 132 119 107 + 150 117 136 153 111 83 + 71 51 43 61 80 131 + 133 118 162 153 113 68 + 128 154 107 108 137 128 + 174 169 89 131 51 34 + 77 178 105 107 81 22 + 32 52 80 88 71 112 + 113 108 122 169 156 112 + 97 91 128 139 64 93 + 118 180 111 74 123 36 + 62 56 81 35 16 9 + 100000000 107 141 110 98 141 + 108 127 144 102 74 62 + 42 34 52 71 122 124 + 109 153 144 104 59 119 + 145 98 99 128 119 166 + 160 80 122 58 25 84 + 169 96 98 72 108 134 + 154 182 190 173 141 155 + 210 133 180 167 114 99 + 93 130 113 66 67 92 + 154 85 37 60 96 96 + 19 110 95 127 134 130 + 100000000 46 75 63 106 116 + 135 162 147 93 166 146 + 138 156 175 199 221 213 + 257 248 208 163 223 249 + 202 201 230 221 120 252 + 184 130 72 129 86 273 + 169 81 174 127 153 173 + 201 209 192 160 174 229 + 152 199 186 133 118 112 + 149 132 85 86 111 173 + 104 56 79 115 115 38 + 129 114 146 153 149 19 + 100000000 29 17 60 70 89 + 116 101 47 135 148 157 + 175 137 153 175 175 219 + 210 183 182 185 211 221 + 220 249 240 85 271 146 + 84 91 148 105 235 123 + 35 193 164 190 210 210 + 240 229 197 211 260 189 + 236 223 170 155 149 186 + 169 122 123 148 210 141 + 93 98 152 152 75 166 + 151 183 190 186 56 45 + 100000000 12 31 41 60 87 + 72 42 106 119 190 208 + 108 124 146 146 190 181 + 154 173 156 182 197 229 + 258 249 56 290 117 55 + 128 185 142 206 94 30 + 202 153 179 199 222 235 + 218 186 200 255 178 225 + 212 159 144 138 175 158 + 111 112 137 199 130 82 + 105 141 141 64 155 140 + 172 179 175 45 57 12 + 100000000 43 53 72 99 84 + 30 118 131 183 201 120 + 136 158 158 202 193 166 + 185 168 194 209 241 270 + 261 68 297 129 67 117 + 174 131 218 106 18 214 + 189 175 195 179 209 214 + 261 234 229 253 300 287 + 234 219 213 250 233 186 + 187 212 270 205 157 175 + 216 216 139 230 202 209 + 202 193 120 122 80 92 + 100000000 10 29 56 41 87 + 75 88 159 177 77 93 + 115 115 159 150 123 142 + 125 151 166 198 227 218 + 105 259 86 24 192 168 + 206 175 63 110 171 179 + 165 185 169 199 204 251 + 224 219 243 290 277 224 + 209 203 240 223 176 177 + 202 260 195 147 165 206 + 206 129 220 192 199 192 + 183 110 112 70 82 49 + 100000000 19 46 31 77 65 + 78 149 167 67 83 105 + 105 149 140 113 132 115 + 141 156 188 217 208 95 + 249 76 14 182 158 196 + 165 53 100 161 212 205 + 225 209 239 244 245 259 + 259 237 284 271 218 203 + 197 234 217 170 171 196 + 241 189 141 146 200 200 + 123 214 199 231 232 223 + 104 93 51 63 30 40 + 100000000 67 71 93 105 118 + 189 207 107 104 117 145 + 167 158 153 172 155 181 + 196 228 254 248 76 286 + 116 54 176 198 190 183 + 93 81 201 184 170 190 + 174 204 209 256 229 224 + 248 295 282 229 214 208 + 245 228 181 182 207 269 + 200 152 175 211 211 134 + 225 197 204 197 188 115 + 150 108 106 87 72 57 + 100000000 36 82 70 83 154 + 172 72 37 59 110 109 + 100 118 137 120 146 161 + 193 196 213 133 228 81 + 86 187 163 201 125 58 + 106 166 148 134 154 138 + 168 173 220 193 188 212 + 259 246 193 178 172 209 + 192 145 146 171 233 164 + 116 139 175 175 98 189 + 161 168 161 152 79 125 + 82 70 85 36 55 82 + 100000000 46 34 47 118 136 + 36 87 89 74 118 109 + 82 101 84 110 125 157 + 186 177 131 218 45 50 + 151 127 165 134 22 70 + 130 213 199 219 203 233 + 238 285 258 253 277 324 + 311 258 243 237 274 257 + 210 211 236 294 229 181 + 199 240 240 163 254 226 + 233 226 217 144 146 104 + 116 83 34 53 80 65 + 100000000 99 112 183 201 101 + 117 139 139 183 174 147 + 166 149 175 190 222 251 + 242 129 283 110 48 216 + 192 230 199 87 134 195 + 153 146 166 150 180 185 + 186 200 200 178 225 212 + 159 144 138 175 158 111 + 112 137 199 130 82 105 + 141 141 64 155 140 172 + 173 164 45 91 48 36 + 79 46 65 92 77 12 + 100000000 59 130 148 48 99 + 101 86 130 121 94 113 + 96 122 137 169 198 189 + 104 230 57 60 117 139 + 131 146 34 36 142 173 + 166 186 170 200 205 206 + 220 220 198 245 232 179 + 164 158 195 178 131 132 + 157 219 150 102 125 161 + 161 84 175 160 192 193 + 184 65 111 68 56 99 + 66 85 112 97 32 20 + 100000000 150 168 68 119 121 + 106 150 141 114 133 116 + 142 157 189 218 209 124 + 250 77 80 137 159 151 + 166 54 56 162 30 16 + 36 64 72 55 120 97 + 92 125 172 156 120 105 + 99 136 147 72 101 126 + 188 119 106 133 68 70 + 88 89 43 50 43 34 + 73 119 76 64 107 74 + 93 110 68 40 28 8 + 100000000 18 37 88 90 75 + 119 110 70 25 85 111 + 64 83 112 103 132 144 + 46 88 66 9 92 135 + 62 64 56 54 40 60 + 59 89 79 144 114 109 + 142 189 173 144 129 123 + 160 171 96 125 150 212 + 143 130 157 92 94 112 + 113 67 74 67 58 97 + 143 100 88 131 86 105 + 92 50 64 52 32 24 + 100000000 19 70 72 57 101 + 92 52 7 67 93 46 + 78 107 98 156 139 28 + 100 90 33 116 117 72 + 88 51 112 98 118 102 + 132 137 202 157 152 185 + 232 216 202 187 181 218 + 223 154 177 202 264 195 + 147 170 150 152 129 171 + 125 132 125 116 110 156 + 113 101 116 67 86 73 + 31 77 65 78 82 100 + 100000000 51 53 38 82 73 + 46 65 48 74 89 121 + 150 141 162 182 9 81 + 148 91 174 98 53 101 + 94 178 164 184 168 198 + 203 268 223 218 251 290 + 259 251 236 230 267 250 + 203 204 229 291 222 174 + 197 216 218 156 237 191 + 198 191 182 137 172 130 + 128 109 94 79 22 58 + 104 92 105 148 166 94 + 100000000 34 126 84 75 112 + 131 114 126 155 181 171 + 207 155 203 103 108 209 + 157 223 100 80 128 160 + 144 130 150 134 164 169 + 234 189 184 217 256 225 + 234 219 213 250 261 186 + 215 240 302 233 211 234 + 182 184 193 203 157 164 + 157 148 174 209 167 165 + 146 131 116 59 95 141 + 129 122 114 132 93 96 + 100000000 92 50 41 78 97 + 80 92 121 147 137 173 + 192 169 102 145 180 123 + 206 66 117 165 126 138 + 124 144 128 158 163 228 + 183 178 211 250 219 228 + 213 207 244 255 180 209 + 234 296 227 191 214 176 + 178 173 197 151 158 151 + 142 154 189 147 145 126 + 111 96 39 75 121 109 + 116 108 126 87 17 15 + 100000000 44 35 72 91 74 + 86 115 141 131 167 172 + 163 96 125 174 117 200 + 60 97 145 120 94 80 + 100 84 114 119 184 139 + 134 167 214 198 184 169 + 163 200 211 136 165 190 + 252 183 170 197 132 134 + 152 153 107 114 107 98 + 137 183 140 128 159 110 + 129 81 74 104 92 72 + 64 82 43 59 57 42 + 100000000 62 28 47 30 56 + 71 103 132 123 196 164 + 52 124 130 73 156 16 + 96 128 76 103 89 109 + 93 123 128 193 148 143 + 176 215 184 193 178 172 + 209 220 145 174 199 261 + 192 179 206 141 143 161 + 162 116 123 116 107 146 + 192 149 137 168 119 138 + 90 83 113 101 81 73 + 91 52 68 41 51 9 + 100000000 37 56 39 51 80 + 106 96 132 205 128 61 + 133 139 82 165 25 105 + 137 85 66 52 72 71 + 101 91 156 126 121 154 + 201 185 156 141 135 172 + 183 108 137 162 224 155 + 142 169 104 106 124 125 + 79 86 79 70 109 155 + 112 100 131 82 101 88 + 46 76 64 44 36 54 + 15 66 68 53 97 88 + 100000000 19 63 89 58 90 + 119 110 168 151 24 96 + 102 45 128 113 68 100 + 63 47 33 53 52 82 + 72 137 107 102 135 182 + 166 137 122 116 153 164 + 89 118 143 205 136 123 + 150 85 87 105 106 60 + 67 60 51 90 136 93 + 81 124 91 110 127 85 + 57 45 25 17 35 54 + 105 107 92 136 127 45 + 100000000 102 128 39 71 100 + 91 149 132 63 105 83 + 26 109 152 79 81 44 + 113 99 119 54 84 100 + 187 109 104 137 184 168 + 203 171 182 219 230 155 + 184 209 271 202 189 216 + 151 137 171 156 126 133 + 126 117 156 202 159 147 + 178 129 148 122 93 123 + 111 91 83 101 62 100 + 73 83 41 32 47 66 + 100000000 26 41 73 102 93 + 215 134 71 143 149 92 + 175 57 115 147 46 129 + 124 128 56 86 102 189 + 111 106 139 186 170 214 + 173 193 230 241 171 200 + 225 287 218 205 241 167 + 139 187 158 142 158 151 + 142 181 227 184 172 203 + 154 173 160 118 148 136 + 116 108 126 87 138 140 + 125 168 159 72 91 135 + 100000000 34 75 104 95 240 + 136 96 168 165 117 191 + 184 140 172 48 95 90 + 94 22 52 68 155 77 + 72 105 152 136 180 139 + 159 196 207 137 166 191 + 253 184 171 207 133 105 + 153 124 108 124 117 108 + 147 193 150 138 169 120 + 139 126 84 114 102 82 + 74 92 53 104 106 91 + 134 125 38 57 101 127 + 100000000 41 70 61 206 102 + 62 134 131 83 157 150 + 106 138 14 113 108 112 + 40 70 86 160 56 51 + 84 131 115 159 118 138 + 175 186 151 180 205 250 + 198 189 225 151 123 171 + 129 126 142 135 126 165 + 211 168 156 187 138 157 + 144 102 132 120 100 92 + 110 71 122 124 109 93 + 84 56 75 93 95 18 + 100000000 29 29 224 61 80 + 152 149 101 144 109 124 + 156 32 146 160 145 101 + 103 119 193 89 84 117 + 119 88 190 151 171 208 + 219 184 213 238 283 231 + 222 271 184 156 204 162 + 159 184 177 168 226 272 + 229 217 248 199 218 186 + 163 193 181 161 153 171 + 132 164 137 147 105 96 + 117 136 105 107 79 61 + 100000000 62 285 32 141 213 + 182 162 177 121 185 217 + 93 84 98 83 69 41 + 57 131 27 22 55 102 + 86 130 89 109 146 157 + 122 151 176 221 169 160 + 209 122 94 142 100 97 + 122 115 106 187 227 190 + 178 216 167 186 173 131 + 154 142 122 114 132 100 + 151 153 138 122 113 85 + 104 122 124 47 29 58 + 100000000 246 67 109 181 120 + 105 115 138 153 178 61 + 146 172 192 220 228 211 + 179 193 248 171 218 205 + 152 137 131 168 151 104 + 105 130 192 123 75 80 + 134 134 57 148 133 165 + 172 168 38 27 34 44 + 65 75 76 121 106 74 + 140 153 176 194 142 158 + 180 180 224 215 188 201 + 190 216 231 239 268 259 + 100000000 290 151 89 110 167 + 124 240 128 62 212 114 + 128 113 69 71 87 161 + 57 52 85 120 89 160 + 119 139 176 187 152 181 + 206 251 199 190 239 152 + 124 172 130 127 152 145 + 136 194 240 197 185 216 + 167 186 173 131 161 149 + 129 121 139 100 151 153 + 138 122 113 85 104 122 + 124 47 29 58 30 253 + 100000000 109 181 150 130 145 + 138 153 185 61 103 89 + 109 93 123 128 193 148 + 143 176 223 207 193 178 + 172 209 220 145 174 199 + 261 192 179 206 141 143 + 161 162 116 123 116 107 + 146 192 149 137 153 119 + 123 66 83 113 101 81 + 73 91 52 44 44 29 + 73 64 37 56 39 65 + 80 112 141 132 199 173 + 100000000 133 139 82 165 89 + 105 137 85 165 151 171 + 155 185 190 237 210 205 + 229 276 263 210 195 189 + 226 209 162 163 188 250 + 181 133 156 192 192 115 + 206 178 185 178 169 96 + 132 90 87 69 53 39 + 53 17 63 51 64 135 + 153 53 90 106 91 135 + 126 99 118 101 127 142 + 174 203 194 115 235 62 + 100000000 168 144 182 151 39 + 87 147 36 62 82 110 + 118 101 74 88 138 73 + 120 107 54 39 33 70 + 81 6 35 60 122 53 + 62 111 24 24 44 43 + 23 55 62 58 134 129 + 142 130 173 140 159 176 + 134 106 94 74 66 84 + 103 154 156 141 185 176 + 136 91 151 177 130 129 + 158 149 171 190 112 154 + 100000000 57 26 201 128 130 + 102 21 7 27 55 63 + 46 111 88 83 116 163 + 147 111 96 90 127 138 + 63 92 117 179 110 97 + 142 59 61 79 80 34 + 41 34 25 82 128 85 + 73 116 83 102 119 77 + 49 37 17 9 27 46 + 97 99 84 128 119 79 + 34 94 120 73 74 103 + 94 141 135 55 97 57 + 100000000 83 144 71 73 47 + 102 128 148 176 184 167 + 69 83 203 61 108 95 + 28 27 7 44 55 60 + 89 96 119 107 119 165 + 90 90 110 38 89 121 + 128 124 191 186 208 196 + 239 206 225 242 200 172 + 160 140 132 150 169 220 + 222 207 251 242 202 157 + 217 243 196 195 178 181 + 228 180 178 220 66 123 + 100000000 267 194 196 168 164 + 150 170 154 184 189 254 + 209 204 237 276 245 254 + 239 233 270 281 206 235 + 260 322 253 217 240 202 + 204 199 223 177 184 177 + 168 180 215 173 171 152 + 137 122 65 101 147 135 + 142 134 152 113 43 41 + 26 70 61 98 117 100 + 112 141 167 157 193 198 + 189 122 151 200 143 226 + 100000000 123 171 146 126 112 + 132 116 146 151 216 171 + 166 199 246 230 216 201 + 195 232 237 168 191 216 + 278 209 161 184 164 166 + 143 185 139 146 139 130 + 124 170 127 115 130 81 + 100 87 45 91 79 92 + 96 114 14 65 67 52 + 96 87 60 79 62 88 + 103 135 164 155 176 196 + 23 95 162 105 188 112 + 100000000 115 108 225 211 231 + 215 245 250 297 270 265 + 289 336 323 270 255 249 + 286 269 222 223 248 306 + 241 193 211 252 252 175 + 266 238 245 238 229 156 + 158 116 128 95 46 65 + 92 77 12 111 124 195 + 213 113 129 151 151 195 + 186 159 178 161 187 202 + 234 263 254 141 295 122 + 60 228 204 242 211 99 + 100000000 207 81 95 80 8 + 38 54 141 63 58 91 + 138 122 166 125 145 182 + 193 123 152 177 239 170 + 157 206 119 91 139 110 + 94 119 112 103 184 224 + 187 175 214 165 184 171 + 129 151 139 119 111 129 + 98 149 151 136 120 111 + 83 102 120 122 45 27 + 56 47 243 88 107 179 + 117 102 143 136 151 175 + 0 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/rbg323.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/rbg323.atsp new file mode 100644 index 0000000..c19aa72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/rbg323.atsp @@ -0,0 +1,6467 @@ +NAME: rbg323 +TYPE: ATSP +COMMENT: Stacker crane application (Ascheuer) +DIMENSION: 323 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 0 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 18 0 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 15 10 0 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 20 20 21 0 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 23 23 23 33 0 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 17 14 12 27 16 0 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 18 18 20 18 27 18 0 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 17 10 11 25 23 25 20 0 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 0 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 17 14 15 23 25 23 12 15 24 0 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 21 21 23 15 28 15 11 23 22 16 0 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 1 15 24 21 7 + 15 24 14 11 28 14 18 9 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 22 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 13 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 11 28 24 28 13 18 12 18 23 10 25 5 28 + 18 13 18 23 28 21 20 18 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 18 + 23 21 12 12 11 24 14 28 12 18 24 10 24 23 24 24 15 + 18 24 23 24 12 21 24 28 13 28 18 23 18 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 7 23 28 10 18 13 + 25 12 14 12 13 25 13 25 14 24 11 11 18 23 12 14 24 + 10 24 23 28 16 21 7 21 14 13 10 23 24 12 24 24 1 + 28 18 13 12 27 10 12 10 14 25 16 18 14 14 12 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 0 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 0 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 0 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 0 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 23 23 23 14 29 14 12 23 23 20 11 15 20 20 25 0 27 + 15 16 16 15 18 4 12 27 23 14 14 15 14 20 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 24 15 14 25 23 11 + 18 24 16 12 29 15 10 11 14 14 12 15 30 12 24 27 11 + 14 14 20 23 14 14 23 14 14 12 14 29 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 23 12 14 23 15 + 12 15 23 16 23 16 21 24 14 14 14 14 14 14 14 14 16 + 14 14 26 14 14 14 14 23 26 12 12 26 15 15 15 29 23 + 27 25 24 24 20 25 25 15 16 15 15 15 10 23 15 12 23 + 23 23 23 29 30 24 25 25 15 28 28 25 25 25 23 26 29 + 23 28 25 15 12 29 25 29 0 21 10 11 24 15 26 11 29 + 21 10 4 24 29 23 23 12 15 24 23 25 23 29 15 25 23 + 23 23 24 29 29 15 15 18 28 23 27 21 24 27 15 18 14 + 24 23 15 15 15 25 16 29 15 10 24 12 25 24 25 24 18 + 12 24 24 24 15 23 25 30 10 30 11 24 16 23 28 23 12 + 28 29 25 18 20 12 15 23 23 26 15 11 23 29 10 18 0 + 27 11 12 15 10 26 11 27 15 25 12 15 15 23 15 12 25 + 10 24 24 29 20 23 11 23 15 10 12 23 24 10 25 24 15 + 29 10 11 15 28 12 15 12 15 27 20 10 15 16 15 30 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 0 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 0 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 0 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 0 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 0 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 16 18 20 26 20 10 18 24 12 12 0 12 12 23 11 24 + 18 11 11 16 0 14 18 24 19 20 20 15 20 12 21 23 20 + 20 20 21 20 20 23 20 20 20 16 20 20 12 20 23 23 12 + 12 23 11 10 26 18 19 12 20 20 10 16 27 18 23 24 16 + 20 20 15 18 20 20 24 8 20 11 20 26 20 24 20 20 20 + 20 20 20 20 20 16 20 16 16 20 20 20 15 10 20 18 10 + 11 18 15 11 15 11 14 23 20 20 20 20 20 20 20 20 11 + 20 20 24 20 20 20 20 16 24 11 11 24 10 18 10 26 16 + 24 23 23 21 12 23 23 18 14 12 18 16 15 16 18 18 16 + 18 18 17 26 27 23 23 23 16 25 25 23 23 23 22 24 26 + 16 25 23 18 12 26 23 26 15 19 15 19 21 11 24 12 26 + 14 15 19 21 26 16 15 20 16 23 18 23 15 26 18 23 16 + 23 16 20 26 26 16 10 12 25 16 24 14 23 24 18 12 19 + 20 19 15 10 14 23 11 26 14 19 23 11 23 20 23 23 15 + 20 23 21 23 15 17 23 27 15 27 19 20 19 15 25 16 11 + 25 26 23 12 12 10 16 18 18 24 18 12 18 26 12 19 15 + 24 16 18 16 15 24 15 24 18 23 10 14 19 18 16 18 23 + 12 23 21 26 14 16 12 16 18 15 11 18 23 15 23 23 12 + 26 19 16 15 25 11 15 11 18 24 12 19 18 11 0 27 23 + + 18 18 16 29 15 29 24 16 24 23 25 24 23 23 12 25 0 + 28 23 23 28 23 0 28 10 19 29 29 27 29 23 14 12 29 + 29 29 21 29 29 23 29 29 29 28 29 15 25 29 11 23 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 15 15 28 + 29 29 23 16 29 29 24 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 29 29 29 18 10 25 25 19 24 28 24 12 18 + 15 12 12 14 23 15 19 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 15 12 12 12 22 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 19 25 19 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 23 18 15 12 15 28 24 23 11 18 0 21 12 15 28 23 24 + 15 19 27 24 27 15 23 12 24 27 15 25 12 15 15 12 23 + 29 12 14 12 27 18 15 14 27 14 28 15 23 20 12 18 25 + 15 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 19 28 28 28 26 10 25 19 28 19 24 27 24 16 28 28 11 + 26 12 19 12 23 18 25 18 28 26 25 16 12 27 11 15 25 + 12 27 28 27 15 25 27 25 28 15 23 27 28 23 24 15 11 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 0 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 0 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 0 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 24 14 31 14 16 24 24 23 14 18 23 23 27 15 28 + 15 21 21 15 23 12 0 28 24 0 14 15 14 23 25 26 14 + 14 14 24 14 14 24 14 14 14 15 14 25 15 14 27 24 14 + 23 26 21 16 31 15 12 14 14 14 16 15 31 0 26 28 10 + 14 14 23 24 14 14 24 18 14 16 14 31 14 29 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 24 16 14 24 20 + 15 15 24 21 24 21 23 26 14 14 14 14 14 14 14 14 21 + 14 14 28 14 14 14 14 24 28 15 15 28 20 15 20 31 24 + 29 27 26 25 23 27 27 15 21 15 15 15 12 24 15 9 24 + 24 24 24 31 31 26 27 27 15 30 31 27 27 27 24 28 31 + 24 30 27 15 15 31 27 31 12 23 11 10 25 15 28 14 31 + 23 11 12 25 31 24 24 10 15 26 24 27 24 31 15 27 24 + 24 24 25 31 31 15 20 23 30 24 28 23 26 29 15 23 18 + 25 24 15 20 15 27 21 31 20 11 26 15 27 25 27 26 23 + 10 26 25 26 15 24 27 31 11 31 10 25 21 24 31 24 15 + 31 31 27 23 23 16 15 24 24 28 15 14 24 31 12 23 12 + 28 10 9 15 12 28 14 28 15 27 16 15 20 24 15 0 27 + 12 26 25 31 23 24 14 24 15 12 15 24 26 11 27 26 15 + 31 11 10 15 31 15 15 15 15 28 23 11 15 21 18 31 27 + + 23 23 23 12 29 12 12 23 23 20 11 14 20 20 25 12 27 + 12 16 16 11 18 0 12 27 23 12 0 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 10 11 12 12 12 11 30 12 24 27 11 + 12 12 20 23 12 12 23 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 10 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 4 21 10 11 24 12 26 11 29 + 21 10 9 24 29 23 23 12 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 14 + 24 23 10 15 10 25 16 29 15 10 24 12 25 24 25 24 18 + 12 24 24 24 10 23 25 30 10 30 11 24 16 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 18 4 + 27 11 12 11 10 26 11 27 12 25 12 10 15 23 11 12 25 + 10 24 24 29 20 23 11 23 12 10 12 23 24 10 25 24 11 + 29 10 11 10 28 12 10 12 12 27 20 10 12 16 14 30 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 0 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 12 14 23 24 23 12 14 14 10 15 12 10 10 20 14 23 + 23 10 10 21 0 18 23 23 12 23 23 20 0 10 16 18 23 + 23 23 12 23 23 12 23 23 23 21 23 15 15 23 21 12 15 + 4 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 14 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 12 23 24 + 12 24 20 23 14 24 20 24 18 11 20 21 16 14 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 12 24 23 21 12 + 12 12 15 24 24 21 11 3 24 12 23 11 18 23 23 10 12 + 15 12 20 11 18 21 10 24 11 20 18 14 20 15 21 18 4 + 23 18 16 18 20 12 20 25 20 25 21 15 10 12 24 12 14 + 24 24 21 10 10 12 21 14 14 23 23 15 14 24 16 9 18 + 23 21 23 21 16 23 15 23 23 21 12 18 11 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 0 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 12 12 12 27 18 27 23 12 12 16 24 23 16 16 15 23 15 + 26 20 20 25 18 24 26 12 12 27 27 25 27 16 0 9 27 + 27 27 12 27 27 12 27 27 27 25 27 15 24 27 15 12 24 + 18 9 20 23 18 26 24 24 27 27 23 25 20 26 0 12 25 + 27 27 16 12 27 27 12 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 15 23 27 12 21 + 23 26 14 20 14 20 15 9 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 15 23 23 12 21 26 21 18 12 + 14 15 15 15 16 11 11 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 15 10 10 25 15 16 10 10 15 12 15 18 + 15 15 10 26 23 18 10 18 24 15 25 25 10 23 12 24 18 + 15 25 24 15 18 12 14 27 25 15 12 15 15 18 26 11 12 + 12 15 15 18 18 25 21 18 15 15 15 15 15 14 26 18 23 + 15 12 25 21 24 11 20 18 21 25 0 23 10 11 11 9 18 + 27 15 15 9 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 15 18 16 23 25 12 12 15 26 24 12 18 24 18 24 + 12 25 26 25 24 15 24 12 26 11 23 24 21 12 25 26 15 + 24 15 10 18 16 12 24 12 26 24 23 12 15 25 15 0 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 0 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 0 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 11 0 10 24 23 24 18 10 18 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 14 24 24 23 24 12 12 12 24 + 0 24 15 24 24 17 24 24 24 24 24 11 21 24 15 17 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 18 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 1 24 24 4 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 0 16 20 20 16 15 24 15 23 3 + 20 14 12 12 12 15 15 24 14 23 24 24 23 10 24 24 0 + 10 10 11 23 23 12 14 14 24 21 23 14 14 14 16 16 23 + 5 21 14 24 20 23 14 23 23 14 23 24 12 20 16 21 23 + 11 23 23 12 23 4 10 24 24 12 10 14 10 23 24 15 7 + 17 5 11 23 23 24 15 12 21 5 18 11 12 20 24 12 16 + 11 14 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 11 14 23 23 23 24 11 14 10 23 9 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 14 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 14 23 12 3 21 1 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 14 2 10 24 23 24 18 10 21 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 16 24 24 23 24 12 12 12 24 + 24 0 18 24 24 20 24 24 24 24 24 11 21 24 15 20 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 21 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 7 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 6 + 20 14 12 12 12 15 16 24 14 23 24 24 23 13 24 24 2 + 10 10 14 23 23 12 14 14 24 21 23 14 14 14 19 16 23 + 3 21 14 24 20 23 14 23 23 16 23 24 12 20 16 21 23 + 11 23 23 12 23 7 12 24 24 12 10 14 10 23 24 15 9 + 20 3 11 23 23 24 15 12 21 3 18 11 12 20 24 12 16 + 11 16 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 14 14 23 23 23 24 11 16 10 23 12 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 16 23 + 18 24 24 24 23 16 21 18 24 16 18 23 16 10 24 24 15 + 23 12 16 23 12 6 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 0 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 14 15 23 25 23 12 15 17 11 14 11 11 11 21 12 23 + 21 0 4 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 0 23 16 23 23 23 20 23 16 14 23 23 16 14 + 10 20 1 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 17 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 1 12 1 12 20 23 23 23 23 23 23 23 23 4 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 7 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 15 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 16 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 12 + 16 14 18 10 16 23 4 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 12 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 12 16 + 23 20 21 20 15 23 14 23 21 23 12 16 12 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 6 11 25 23 + + 10 10 4 25 23 25 20 6 17 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 12 25 25 24 25 12 11 12 25 + 25 25 14 25 0 16 25 25 25 24 25 10 23 25 14 16 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 3 25 25 17 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 3 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 11 12 14 14 24 15 23 24 24 23 10 24 24 10 + 1 2 10 23 23 12 12 12 24 20 21 12 12 12 15 15 23 + 10 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 11 23 10 11 25 24 12 3 12 11 23 24 14 10 + 16 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 12 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 2 0 15 24 23 1 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 1 24 24 14 + 23 12 12 23 12 10 23 10 24 23 21 2 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 0 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 10 10 0 25 23 25 20 1 12 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 11 12 25 + 25 25 10 25 25 11 0 25 25 24 25 11 23 25 14 11 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 1 25 25 12 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 1 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 11 12 14 14 24 15 23 24 24 23 10 24 24 10 + 6 2 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 11 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 11 23 10 11 25 24 12 1 12 11 23 24 14 10 + 11 11 11 23 23 24 16 14 20 11 16 12 12 18 24 14 18 + 11 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 2 4 15 24 23 6 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 3 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 2 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 9 2 10 24 23 24 18 10 16 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 11 24 24 23 24 12 12 12 24 + 24 24 12 24 24 15 24 0 24 24 24 11 21 24 15 15 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 16 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 1 24 24 2 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 1 + 20 14 12 12 12 15 15 24 14 23 24 24 23 8 24 24 2 + 10 10 9 23 23 12 14 14 24 21 23 14 14 14 14 16 23 + 8 21 14 24 20 23 14 23 23 11 23 24 12 20 16 21 23 + 11 23 23 12 23 2 10 24 24 12 10 14 10 23 24 15 4 + 15 8 11 23 23 24 15 12 21 8 18 11 12 20 24 12 16 + 11 11 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 9 14 23 23 23 24 11 14 10 23 7 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 12 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 12 23 12 1 21 1 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 10 10 1 25 23 25 20 0 11 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 12 12 25 + 25 25 10 25 25 10 25 25 0 24 25 12 23 25 14 10 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 2 25 25 11 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 12 20 25 2 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 12 12 14 14 24 15 23 24 24 23 10 24 24 10 + 7 3 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 12 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 12 23 10 11 25 24 12 2 12 12 23 24 14 10 + 10 12 12 23 23 24 16 14 20 12 16 12 12 18 24 14 18 + 12 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 12 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 3 6 15 24 23 7 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 4 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 3 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 0 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 10 10 1 25 23 25 20 0 11 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 10 25 25 24 25 12 12 12 25 + 25 25 10 25 25 10 25 25 25 24 0 12 23 25 14 10 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 2 25 25 11 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 12 20 25 2 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 15 16 24 16 23 10 + 18 12 12 12 12 14 14 24 15 23 24 24 23 10 24 24 10 + 7 3 10 23 23 12 12 12 24 20 21 12 12 12 10 15 23 + 12 20 12 24 21 23 12 23 23 12 24 24 11 21 15 23 23 + 12 24 23 12 23 10 11 25 24 12 2 12 12 23 24 14 10 + 10 12 12 23 23 24 16 14 20 12 16 12 12 18 24 14 18 + 12 10 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 12 12 24 10 12 23 24 23 24 10 15 11 21 10 21 + 21 23 14 14 12 20 24 3 6 15 24 23 7 23 23 14 23 + 16 24 24 24 23 15 23 16 24 14 20 23 16 4 24 24 14 + 23 12 11 23 12 10 23 10 24 23 21 3 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 0 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 0 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 6 4 10 24 23 24 18 10 13 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 9 24 24 23 24 12 12 12 24 + 24 24 10 24 24 12 24 24 24 24 24 11 21 0 15 12 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 13 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 0 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 4 16 20 20 16 15 24 15 23 1 + 20 14 12 12 12 15 15 24 14 23 24 24 23 5 24 24 4 + 10 10 6 23 23 12 14 14 24 21 23 14 14 14 11 16 23 + 10 21 14 24 20 23 14 23 23 11 23 24 12 20 16 21 23 + 11 23 23 12 23 0 10 24 24 12 10 14 10 23 24 15 2 + 12 10 11 23 23 24 15 12 21 10 18 11 12 20 24 12 16 + 11 9 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 6 14 23 23 23 24 11 14 10 23 4 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 12 23 + 18 24 24 24 23 16 21 18 24 15 18 23 15 10 24 24 15 + 23 12 12 23 12 1 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 0 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 0 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 21 21 23 15 28 15 11 23 22 16 10 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 1 15 24 21 0 + 15 24 14 11 28 14 18 9 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 22 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 13 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 11 28 24 28 13 18 12 18 23 10 25 5 28 + 18 13 18 23 28 21 20 18 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 18 + 23 21 12 12 11 24 14 28 12 18 24 10 24 23 24 24 15 + 18 24 23 24 12 21 24 28 13 28 18 23 18 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 7 23 28 10 18 13 + 25 12 14 12 13 25 13 25 14 24 11 11 18 23 12 14 24 + 10 24 23 28 16 21 7 21 14 13 10 23 24 12 24 24 1 + 28 18 13 12 27 10 12 10 14 25 16 18 14 14 12 28 24 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 0 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 0 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 12 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 0 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 0 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 0 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 14 31 14 16 24 24 23 14 18 23 23 27 15 28 + 15 21 21 15 23 12 0 28 24 14 14 15 14 23 25 26 14 + 14 14 24 14 14 24 14 14 14 15 14 25 15 14 27 24 14 + 23 26 21 16 31 0 12 14 14 14 16 15 31 0 26 28 10 + 14 14 23 24 14 14 24 18 14 16 14 31 14 29 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 24 16 14 24 20 + 15 15 24 21 24 21 23 26 14 14 14 14 14 14 14 14 21 + 14 14 28 14 14 14 14 24 28 15 15 28 20 15 20 31 24 + 29 27 26 25 23 27 27 15 21 15 15 15 12 24 15 9 24 + 24 24 24 31 31 26 27 27 15 30 31 27 27 27 24 28 31 + 24 30 27 15 15 31 27 31 12 23 11 10 25 15 28 14 31 + 23 11 12 25 31 24 24 10 15 26 24 27 24 31 15 27 24 + 24 24 25 31 31 15 20 23 30 24 28 23 26 29 15 23 18 + 25 24 15 20 15 27 21 31 20 11 26 15 27 25 27 26 23 + 10 26 25 26 15 24 27 31 11 31 10 25 21 24 31 24 15 + 31 31 27 23 23 16 15 24 24 28 15 14 24 31 12 23 12 + 28 10 9 15 12 28 14 28 15 27 16 15 20 24 15 0 27 + 12 26 25 31 23 24 14 24 15 12 15 24 26 11 27 26 15 + 31 11 10 15 31 15 15 15 15 28 23 11 15 21 18 31 27 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 0 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 0 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 21 21 23 15 28 15 11 23 21 16 2 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 9 15 24 21 0 + 15 24 14 11 28 14 10 1 0 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 2 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 0 23 28 10 15 11 + 25 12 14 12 10 25 5 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 0 21 14 10 10 23 24 12 24 24 9 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 14 14 12 27 16 27 23 12 17 18 24 23 18 18 6 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 16 27 27 27 26 27 12 24 27 10 16 24 + 20 10 21 23 16 27 24 24 27 0 23 26 18 27 10 12 26 + 27 27 18 12 27 27 17 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 12 23 27 23 16 14 + 12 6 10 11 18 10 12 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 3 3 26 14 15 6 3 6 15 11 16 + 14 14 1 27 24 16 6 16 25 16 25 26 11 24 12 24 16 + 16 25 25 11 16 14 15 27 26 10 12 6 15 16 27 10 14 + 16 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 3 12 10 10 20 + 27 10 11 10 25 14 8 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 12 23 25 23 12 26 27 10 + 24 10 12 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 15 16 21 25 21 11 16 22 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 18 21 21 16 21 12 20 21 21 + 21 21 19 21 21 21 21 21 21 18 21 18 12 21 23 21 12 + 11 21 10 11 25 20 18 12 21 21 0 18 26 20 21 24 18 + 21 21 13 16 21 21 22 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 5 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 5 20 6 25 15 + 24 23 21 20 12 23 23 20 12 14 20 18 14 15 20 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 20 23 25 + 15 24 23 20 12 25 23 25 15 18 16 18 20 12 23 12 25 + 12 16 18 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 21 15 18 25 25 18 6 11 24 15 24 12 21 24 20 11 18 + 18 18 16 4 15 23 10 25 12 18 21 12 23 18 23 21 13 + 21 21 20 21 16 15 23 26 16 26 18 18 18 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 18 15 + 24 18 20 18 14 23 13 24 20 23 11 15 18 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 18 18 16 25 12 16 12 20 24 12 18 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 0 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 0 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 0 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 0 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 23 24 23 24 10 19 12 20 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 0 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 0 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 14 14 12 27 16 27 23 12 17 18 24 23 18 18 6 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 16 27 27 27 26 27 12 24 27 10 16 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 0 27 18 12 27 27 17 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 12 23 27 23 16 14 + 12 6 10 11 18 10 12 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 3 3 26 14 15 6 3 6 15 11 16 + 14 14 1 27 24 16 6 16 25 16 25 26 11 24 12 24 16 + 16 25 25 11 16 14 15 27 26 10 12 6 15 16 27 10 14 + 16 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 3 12 10 10 20 + 27 10 11 10 25 14 8 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 12 23 25 23 12 26 27 10 + 24 10 12 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 21 21 23 15 28 15 11 23 21 16 0 12 16 16 24 11 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 11 15 24 21 2 + 15 24 14 11 28 14 10 1 15 15 11 12 28 14 24 25 12 + 15 0 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 11 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 11 25 4 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 2 23 28 10 15 11 + 25 12 14 12 10 25 3 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 2 21 14 10 10 23 24 12 24 24 11 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 0 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 0 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 21 21 23 15 28 15 11 23 21 16 2 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 9 15 24 21 0 + 15 24 14 11 28 14 10 1 15 15 11 12 28 14 24 25 12 + 15 15 16 23 0 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 2 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 0 23 28 10 15 11 + 25 12 14 12 10 25 5 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 0 21 14 10 10 23 24 12 24 24 9 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 21 21 23 15 28 15 11 23 21 16 1 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 10 15 24 21 1 + 15 24 14 11 28 14 10 0 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 0 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 3 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 1 23 28 10 15 11 + 25 12 14 12 10 25 4 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 1 21 14 10 10 23 24 12 24 24 10 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 0 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 22 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 0 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 14 14 12 27 16 27 23 12 15 18 24 23 18 18 9 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 14 27 27 27 26 27 12 24 27 10 14 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 15 23 0 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 9 10 11 18 10 10 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 1 1 26 14 15 3 1 9 14 11 16 + 14 14 3 27 24 16 3 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 9 15 16 27 10 14 + 14 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 1 12 10 10 20 + 27 10 11 10 25 14 5 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 10 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 0 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 14 14 12 27 16 27 23 12 16 18 24 23 18 18 8 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 15 27 27 27 26 27 12 24 27 10 15 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 16 23 27 23 0 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 8 10 11 18 10 11 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 2 2 26 14 15 4 2 8 14 11 16 + 14 14 2 27 24 16 4 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 8 15 16 27 10 14 + 15 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 2 12 10 10 20 + 27 10 11 10 25 14 7 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 11 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 0 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 14 14 15 23 25 23 12 15 16 11 14 11 11 11 21 12 23 + 21 1 3 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 23 23 15 23 23 23 20 23 16 14 23 23 15 14 + 10 20 0 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 16 11 23 12 23 25 0 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 0 12 2 12 20 23 23 23 23 23 23 23 23 3 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 6 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 15 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 11 + 16 14 18 10 16 23 3 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 11 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 11 16 + 23 20 21 20 15 23 14 23 21 23 12 16 11 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 8 11 25 23 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 0 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 18 18 20 18 27 18 9 20 24 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 19 18 18 14 18 14 23 23 18 + 18 18 21 18 18 23 18 18 18 15 18 21 11 18 24 23 11 + 12 23 12 6 27 16 19 11 18 18 5 15 27 16 23 24 15 + 18 18 15 20 18 18 24 10 18 11 18 27 18 25 0 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 9 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 14 12 16 15 15 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 22 24 27 + 18 25 23 16 12 27 23 27 15 19 14 19 23 10 24 11 27 + 15 15 19 23 27 18 16 19 15 23 20 23 16 27 16 24 18 + 23 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 19 + 21 19 14 11 12 24 12 27 14 19 23 10 23 21 24 23 15 + 19 23 23 23 14 18 23 27 15 27 19 21 19 16 26 18 10 + 26 27 24 12 14 10 15 20 20 24 16 11 20 27 12 19 15 + 24 15 16 15 15 24 15 24 16 24 9 12 19 20 15 16 24 + 12 23 23 27 14 18 11 18 16 15 10 20 23 14 24 23 11 + 27 19 15 14 26 10 14 10 16 24 14 19 16 12 10 27 24 + + 11 11 12 24 24 24 15 12 14 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 11 24 24 23 24 10 14 15 24 + 24 24 11 24 24 12 24 24 24 23 24 12 18 24 18 12 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 10 12 24 24 14 14 24 15 24 24 24 23 24 0 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 10 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 18 23 12 20 23 23 20 11 23 23 11 + 12 12 11 24 24 15 16 16 23 23 23 16 16 16 11 20 24 + 11 23 16 23 16 24 16 24 21 9 23 23 14 16 20 18 24 + 0 23 21 14 24 11 10 24 23 15 12 16 10 24 23 18 11 + 12 11 12 24 24 23 12 11 23 11 21 10 15 23 23 11 14 + 12 11 23 12 21 18 12 24 12 23 15 16 16 12 18 15 11 + 24 15 14 15 23 11 16 24 23 24 23 12 12 10 23 11 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 11 21 + 21 23 23 23 20 20 18 21 23 18 15 21 12 12 23 23 18 + 20 15 14 24 10 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 0 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 6 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 0 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 14 14 15 23 25 23 12 15 14 11 14 11 11 11 21 12 23 + 21 4 0 20 10 16 21 23 14 23 23 18 23 11 18 20 23 + 23 23 14 23 23 14 23 23 23 20 23 16 14 23 23 14 14 + 10 20 3 12 25 21 15 14 23 23 12 20 25 21 20 23 20 + 23 23 11 15 23 23 14 11 23 12 23 25 23 24 23 23 23 + 23 0 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 3 12 6 12 20 23 23 23 23 23 23 23 23 0 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 2 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 14 24 21 21 12 25 21 25 16 12 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 14 14 16 25 25 20 10 10 24 14 23 12 20 24 21 11 11 + 16 14 18 10 16 23 0 25 10 18 20 12 21 16 23 20 10 + 23 20 18 20 18 14 21 25 18 25 20 16 8 12 24 14 12 + 24 25 23 11 11 12 20 15 15 23 21 14 15 25 15 10 16 + 23 20 21 20 15 23 14 23 21 23 12 16 10 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 11 11 25 23 + + 14 14 12 27 16 27 23 12 15 18 24 23 18 18 9 24 12 + 27 21 21 26 20 25 27 12 14 27 27 25 27 18 11 10 27 + 27 27 14 27 27 14 27 27 27 26 27 12 24 27 10 14 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 10 12 26 + 27 27 18 12 27 27 15 23 27 23 27 16 27 12 27 27 27 + 27 27 0 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 11 23 27 23 16 14 + 12 9 10 11 18 10 10 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 1 1 26 14 15 3 1 9 14 11 16 + 14 14 3 27 24 16 3 16 25 16 25 26 11 24 11 24 16 + 16 25 25 11 16 14 15 27 26 10 12 9 15 16 27 10 14 + 14 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 14 25 23 25 10 21 16 23 25 10 24 1 12 10 10 20 + 27 10 11 10 25 14 5 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 12 26 27 26 24 11 24 12 27 10 23 25 23 12 26 27 10 + 24 10 11 16 18 14 24 14 27 24 24 12 10 25 10 10 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 18 18 20 18 27 18 2 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 0 27 16 12 11 18 18 1 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 4 18 27 18 25 18 18 18 + 18 18 18 0 18 18 18 15 18 18 18 18 16 2 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 12 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 3 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 2 12 12 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 12 12 14 23 24 23 12 14 18 10 15 12 10 10 20 14 23 + 23 10 10 21 4 18 23 23 14 23 23 20 23 10 16 18 23 + 23 23 15 23 23 17 23 23 23 21 23 15 15 23 21 17 15 + 0 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 18 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 0 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 16 23 24 + 12 24 20 23 14 24 20 24 18 14 20 21 16 14 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 12 24 23 21 12 + 17 12 15 24 24 21 11 1 24 12 23 11 18 23 23 5 14 + 15 14 20 11 18 21 10 24 11 20 18 14 20 15 21 18 9 + 23 18 16 18 20 12 20 25 20 25 21 15 14 12 24 12 14 + 24 24 21 5 10 12 21 14 14 23 23 15 14 24 16 14 18 + 23 21 23 21 16 23 15 23 23 21 12 18 14 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 0 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 0 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 0 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 0 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 18 18 20 18 27 18 3 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 1 27 16 14 11 18 18 0 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 6 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 0 18 18 16 3 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 14 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 14 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 14 16 26 18 10 + 26 27 24 12 14 4 15 20 20 24 16 11 20 27 12 14 12 + 24 15 16 15 12 24 11 24 16 24 3 12 14 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 0 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 15 15 14 28 15 28 24 14 17 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 16 28 28 28 27 28 12 24 28 6 16 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 17 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 0 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 12 23 27 23 15 15 + 12 10 11 12 20 8 12 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 12 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 1 15 + 16 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 8 23 15 23 26 11 24 10 12 8 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 6 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 12 27 27 27 25 10 24 12 27 12 24 25 23 14 27 27 6 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 6 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 3 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 0 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 0 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 21 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 15 15 14 28 15 28 24 14 16 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 12 11 28 + 28 28 15 28 28 15 28 28 28 27 28 12 24 28 8 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 16 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 0 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 11 23 27 23 15 15 + 12 10 11 12 20 7 11 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 11 10 10 27 12 14 10 10 10 15 10 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 11 24 15 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 2 15 + 15 15 12 15 15 27 23 21 12 15 11 18 11 12 27 21 23 + 12 15 26 23 25 7 23 15 23 26 11 24 10 12 7 11 21 + 28 11 12 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 8 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 11 27 27 27 25 10 24 11 27 11 24 25 23 14 27 27 8 + 25 11 12 15 20 15 24 15 27 25 24 14 11 26 8 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 2 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 0 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 15 15 16 21 25 21 11 16 21 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 16 21 21 16 21 12 20 21 21 + 21 21 18 21 21 20 21 21 21 18 21 18 12 21 23 20 12 + 11 21 10 11 25 20 16 12 21 21 11 18 26 20 21 24 18 + 21 21 12 16 21 21 21 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 0 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 3 20 5 25 15 + 24 23 21 20 12 23 23 20 11 14 20 18 14 15 20 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 19 23 25 + 15 24 23 20 12 25 23 25 15 16 16 18 20 12 23 12 25 + 12 16 16 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 20 15 18 25 25 18 5 11 24 15 24 12 21 24 20 11 16 + 18 16 16 2 15 23 10 25 11 16 21 12 23 18 23 21 12 + 21 21 20 21 16 15 23 26 16 26 18 18 16 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 16 15 + 24 18 20 18 14 23 12 24 20 23 11 15 16 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 16 18 16 25 12 16 12 20 24 12 16 20 10 10 26 23 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 0 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 5 15 23 11 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 0 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 0 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 10 11 24 23 24 16 12 24 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 19 24 24 23 24 11 12 14 24 + 24 24 21 24 24 23 24 24 24 23 24 12 20 24 16 23 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 15 20 23 + 24 24 15 11 24 24 24 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 0 16 24 11 14 + 18 24 10 0 10 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 19 14 24 14 23 10 + 21 15 14 12 11 16 19 24 14 21 24 23 21 16 24 24 10 + 11 11 17 23 24 14 15 15 23 23 23 15 15 15 22 18 23 + 10 23 15 24 18 23 15 23 23 19 23 23 12 18 19 20 23 + 10 23 23 12 23 10 15 24 23 14 11 15 0 23 24 16 12 + 23 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 19 + 12 19 23 14 23 16 12 23 14 23 15 18 15 12 16 14 15 + 24 14 12 14 23 17 15 24 23 24 23 12 19 6 23 15 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 19 23 + 20 23 24 23 21 18 20 20 24 19 16 23 19 11 23 24 16 + 21 14 19 23 14 10 20 10 24 21 18 11 14 23 16 15 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 0 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 0 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 10 10 11 24 23 24 16 11 14 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 10 24 24 23 24 11 12 14 24 + 24 24 10 24 24 12 24 24 24 23 24 12 20 24 16 12 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 14 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 10 16 24 11 14 + 18 24 0 12 0 12 0 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 10 23 24 14 15 15 23 23 23 15 15 15 11 18 23 + 10 23 15 24 18 23 15 23 23 10 23 23 12 18 18 20 23 + 10 23 23 12 23 10 4 24 23 14 11 15 10 23 24 16 10 + 12 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 10 23 14 23 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 10 15 24 23 24 23 12 12 4 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 12 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 12 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 0 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 12 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 6 21 11 10 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 6 11 24 12 11 27 24 12 + 21 25 20 15 31 10 13 12 11 11 15 6 31 10 25 28 0 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 6 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 0 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 6 12 24 10 10 24 + 24 24 24 31 31 25 26 26 6 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 11 23 10 13 25 14 27 12 31 + 23 10 13 25 31 24 23 13 6 25 24 26 23 31 10 27 24 + 24 24 24 31 31 6 18 21 29 24 28 23 25 28 10 21 16 + 24 24 10 18 11 27 20 31 18 13 25 14 26 24 27 25 21 + 13 25 25 25 10 24 26 31 10 31 13 24 20 23 30 24 14 + 30 31 27 21 23 15 6 24 24 27 10 12 24 31 12 21 11 + 28 4 10 6 12 27 12 28 10 27 15 11 18 24 6 10 27 + 12 25 25 31 23 24 12 24 10 12 14 24 25 10 27 25 12 + 31 13 9 10 30 14 10 14 10 28 23 13 10 20 16 31 27 + + 23 23 23 18 28 18 12 23 23 18 10 19 18 18 24 19 26 + 19 15 15 19 16 10 12 26 23 18 18 19 18 18 24 24 18 + 18 18 23 18 18 23 18 18 18 19 18 23 19 18 25 23 10 + 16 24 15 12 28 19 0 10 18 18 14 19 29 12 24 26 13 + 18 18 18 23 18 18 23 12 18 12 18 28 18 27 18 18 18 + 18 18 18 18 18 23 18 19 23 18 18 18 21 12 18 23 14 + 12 19 21 15 21 15 20 24 18 0 18 18 18 18 18 18 15 + 18 18 25 18 18 18 18 23 25 14 11 25 14 19 14 28 23 + 27 24 24 24 18 25 25 19 15 19 19 19 4 23 19 13 23 + 23 23 23 28 29 24 24 24 19 27 28 24 24 24 23 25 28 + 23 27 24 19 11 28 24 28 10 20 11 12 24 19 25 12 28 + 20 11 10 24 28 23 21 14 19 24 23 24 21 28 19 25 23 + 23 23 23 28 28 19 14 16 27 23 26 20 24 27 19 19 12 + 23 23 19 14 19 25 15 28 14 11 24 13 24 23 25 24 16 + 14 24 24 24 19 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 19 18 12 19 23 23 25 19 10 23 28 9 16 10 + 26 12 13 19 4 25 10 26 19 25 12 19 14 23 19 12 25 + 13 24 24 28 18 23 10 23 19 4 11 23 24 13 25 24 19 + 28 11 12 19 28 11 19 13 19 26 19 11 19 19 19 29 25 + + 12 12 12 23 24 23 14 12 12 9 16 15 8 8 18 15 23 + 23 11 11 23 10 20 23 23 12 23 23 21 23 4 15 16 23 + 23 23 12 23 23 12 23 23 23 23 23 15 16 23 20 12 16 + 10 16 11 14 24 23 18 16 23 23 14 23 24 23 16 23 23 + 23 23 0 12 23 23 12 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 15 14 23 12 12 + 15 23 11 11 11 11 15 16 23 23 0 23 23 23 23 23 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 4 20 20 23 11 18 23 23 18 12 23 23 12 + 12 12 12 24 24 16 18 18 23 23 24 18 18 18 12 21 24 + 15 23 18 23 15 24 18 24 20 10 21 23 15 15 21 16 24 + 10 21 20 15 24 12 11 23 23 16 12 18 15 24 23 20 12 + 12 15 15 24 24 23 12 10 23 15 23 15 16 23 23 15 12 + 15 12 21 12 20 20 11 24 12 21 16 15 18 14 20 16 10 + 23 16 15 16 21 12 18 24 21 24 23 14 11 11 24 12 15 + 24 24 20 15 9 14 23 12 12 21 23 16 12 24 18 10 20 + 23 23 23 23 18 21 16 23 23 20 14 20 12 12 23 23 20 + 18 16 15 24 0 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 15 21 23 15 15 24 20 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 0 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 6 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 12 12 12 27 18 27 23 12 12 16 24 23 16 16 15 23 15 + 26 20 20 25 18 24 26 12 12 27 27 25 27 16 15 9 27 + 27 27 12 27 27 12 27 27 27 25 27 15 24 27 15 12 24 + 18 9 20 23 18 26 24 24 27 27 23 25 20 26 0 12 25 + 27 27 16 12 27 27 12 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 15 23 27 12 21 + 23 26 14 20 14 20 15 9 27 27 27 27 0 27 27 27 20 + 27 27 12 27 27 27 27 12 15 23 23 12 21 26 21 18 12 + 14 15 15 15 16 11 11 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 15 10 10 25 15 16 10 10 15 12 15 18 + 15 15 10 26 23 18 10 18 24 15 25 25 10 23 12 24 18 + 15 25 24 15 18 12 14 27 25 15 12 15 15 18 26 11 12 + 12 15 15 18 18 25 21 18 15 15 15 15 15 14 26 18 23 + 15 12 25 21 24 11 20 18 21 25 0 23 10 11 11 9 18 + 27 15 15 9 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 15 18 16 23 25 12 12 15 26 24 12 18 24 18 24 + 12 25 26 25 24 15 24 12 26 11 23 24 21 12 25 26 15 + 24 15 10 18 16 12 24 12 26 24 23 12 15 25 15 0 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 18 18 20 18 27 18 2 20 18 14 11 11 14 14 23 11 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 4 27 16 12 11 18 18 6 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 0 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 2 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 0 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 11 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 10 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 1 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 2 12 11 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 11 27 24 + + 21 21 23 15 28 15 11 23 21 16 1 12 16 16 24 10 25 + 14 14 14 12 15 11 14 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 21 15 15 15 12 15 23 10 15 24 21 1 + 15 24 14 11 28 14 10 0 15 15 11 12 28 14 24 25 12 + 15 15 16 23 15 15 21 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 0 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 10 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 21 25 28 + 21 27 24 14 10 28 24 28 11 18 12 12 23 10 25 3 28 + 18 12 11 23 28 21 20 15 12 24 23 24 20 28 14 24 21 + 21 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 12 + 23 21 12 12 11 24 14 28 12 12 24 10 24 23 24 24 15 + 15 24 23 24 12 21 24 28 12 28 12 23 14 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 1 23 28 10 15 11 + 25 12 14 12 10 25 4 25 14 24 11 11 12 23 12 14 24 + 10 24 23 28 16 21 1 21 14 10 10 23 24 12 24 24 10 + 28 12 12 12 27 10 12 10 14 25 16 12 14 14 12 28 24 + + 12 12 12 23 24 23 14 12 18 0 16 12 1 1 18 15 23 + 23 11 11 23 10 20 23 23 14 23 23 21 23 4 15 16 23 + 23 23 15 23 23 17 23 23 23 23 23 14 16 23 20 17 16 + 10 16 11 14 24 23 18 16 23 23 14 23 24 23 16 23 23 + 23 23 9 12 23 23 18 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 11 14 23 12 12 + 15 23 11 11 11 11 10 16 23 23 23 23 23 23 23 0 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 4 20 20 23 11 18 23 23 18 12 23 23 12 + 12 12 12 24 24 16 18 18 23 23 24 18 18 18 16 21 24 + 12 23 18 23 15 24 18 24 20 14 21 23 15 15 21 16 24 + 10 21 20 15 24 12 11 23 23 16 12 18 11 24 23 20 12 + 17 12 14 24 24 23 12 10 23 12 23 10 16 23 23 10 14 + 14 14 21 12 20 20 11 24 12 21 16 15 18 14 20 16 10 + 23 16 15 16 21 12 18 24 21 24 23 14 14 11 24 12 15 + 24 24 20 10 0 14 23 12 12 21 23 16 12 24 18 14 20 + 23 23 23 23 18 21 16 23 23 20 14 20 14 12 23 23 20 + 18 16 15 24 8 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 5 21 23 11 12 24 20 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 0 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 25 23 + + 10 10 11 24 23 24 16 11 14 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 10 24 24 23 24 11 12 14 24 + 24 24 10 24 24 12 24 24 24 23 24 12 20 24 16 12 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 14 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 10 16 24 11 14 + 18 24 0 12 0 12 10 14 24 24 24 24 24 24 24 24 12 + 0 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 10 23 24 14 15 15 23 23 23 15 15 15 11 18 23 + 10 23 15 24 18 23 15 23 23 10 23 23 12 18 18 20 23 + 10 23 23 12 23 10 4 24 23 14 11 15 10 23 24 16 10 + 12 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 10 23 14 23 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 10 15 24 23 24 23 12 12 4 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 12 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 12 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 16 16 15 28 14 28 24 15 16 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 16 28 28 27 28 21 12 12 28 + 28 28 16 28 28 16 28 28 28 27 28 14 25 28 10 16 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 12 10 27 + 28 28 21 15 28 28 16 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 0 4 28 28 28 28 16 10 24 24 9 23 28 23 14 16 + 11 11 12 12 21 10 10 28 23 25 28 27 25 16 28 28 16 + 15 15 16 14 15 12 11 11 27 12 12 11 11 11 16 10 14 + 16 12 11 28 24 14 11 14 26 20 27 27 12 24 9 25 14 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 16 16 14 14 14 27 23 23 12 16 10 20 12 11 28 23 24 + 14 16 27 23 26 10 23 14 23 27 12 24 11 14 10 12 23 + 28 12 12 12 27 16 11 15 27 15 27 14 23 18 12 16 24 + 12 14 10 23 21 24 27 15 15 10 28 25 15 14 25 23 26 + 10 27 28 27 25 10 25 10 28 10 24 26 23 15 27 28 10 + 25 12 12 14 21 16 25 16 28 25 24 15 12 27 10 12 25 + 14 27 27 27 12 24 27 24 28 10 21 27 28 23 24 15 10 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 0 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 12 25 6 + 28 23 23 28 23 27 28 4 18 29 29 27 29 23 14 12 29 + 29 29 18 29 29 18 29 29 29 28 29 15 25 29 11 18 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 12 9 28 + 29 29 23 16 29 29 18 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 0 29 29 29 18 10 25 25 13 24 28 24 12 18 + 10 12 12 14 23 11 13 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 12 12 12 12 18 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 13 25 13 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 18 18 15 12 12 28 24 23 11 18 6 21 12 10 28 23 24 + 15 18 27 24 27 11 23 12 24 27 12 25 12 15 11 12 23 + 29 12 14 12 27 18 12 14 27 14 28 15 23 20 12 18 25 + 12 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 13 28 28 28 26 10 25 13 28 13 24 27 24 16 28 28 11 + 26 12 14 12 23 18 25 18 28 26 25 16 12 27 11 12 25 + 12 27 28 27 12 25 27 25 28 9 23 27 28 23 24 14 11 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 12 25 10 + 28 23 23 28 23 27 28 0 18 29 29 27 29 23 14 12 29 + 29 29 18 29 29 18 29 29 29 28 29 15 25 29 11 18 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 12 4 28 + 29 29 23 16 29 29 18 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 0 29 29 18 10 25 25 10 24 28 24 12 18 + 10 12 12 14 23 11 11 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 12 12 12 12 18 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 10 25 12 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 18 18 15 12 12 28 24 23 11 18 10 21 12 10 28 23 24 + 15 18 27 24 27 11 23 12 24 27 12 25 12 15 11 12 23 + 29 12 14 12 27 18 12 14 27 14 28 15 23 20 12 18 25 + 12 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 9 28 28 28 26 10 25 9 28 11 24 27 24 16 28 28 11 + 26 12 14 12 23 18 25 18 28 26 25 16 12 27 11 12 25 + 12 27 28 27 12 25 27 25 28 4 23 27 28 23 24 14 11 + + 18 18 20 18 27 18 0 20 18 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 18 18 18 18 18 18 18 15 18 21 11 18 24 18 11 + 12 23 12 2 27 16 12 11 18 18 3 15 27 16 23 24 15 + 18 18 14 20 18 18 18 10 18 2 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 0 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 0 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 12 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 18 24 27 + 18 25 23 16 10 27 23 27 12 15 14 15 23 10 24 11 27 + 15 14 12 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 18 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 10 + 21 18 14 11 12 24 12 27 11 14 23 10 23 21 24 23 12 + 18 23 23 23 14 18 23 27 14 27 15 21 12 16 26 18 10 + 26 27 24 12 14 1 15 20 20 24 16 11 20 27 12 12 12 + 24 15 16 15 12 24 11 24 16 24 0 12 11 20 15 16 24 + 12 23 23 27 14 18 11 18 16 12 10 20 23 14 24 23 11 + 27 14 15 14 26 10 14 10 16 24 14 14 16 12 10 27 24 + + 18 18 16 29 12 29 24 16 18 23 25 24 23 23 19 25 19 + 28 23 23 28 23 27 28 9 18 29 29 27 29 23 19 13 29 + 29 29 18 29 29 18 29 29 29 28 29 19 25 29 19 18 25 + 23 13 23 24 19 28 26 25 29 29 24 28 14 28 12 4 28 + 29 29 23 16 29 29 18 24 29 24 29 19 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 13 29 29 29 29 29 29 29 29 23 + 29 29 13 29 29 29 0 18 19 25 25 10 24 28 24 19 18 + 10 19 19 19 23 11 11 28 23 26 28 28 26 18 28 28 18 + 16 16 18 19 14 19 12 12 28 19 12 12 12 19 18 19 19 + 19 14 14 28 25 19 12 19 27 21 27 28 14 25 10 25 12 + 21 27 27 19 19 18 20 29 28 19 16 19 20 19 28 14 18 + 18 19 19 19 12 28 24 23 19 19 19 21 19 10 28 23 24 + 19 18 27 24 27 11 23 19 24 27 12 25 12 15 11 13 23 + 29 19 19 13 27 18 12 14 27 14 28 15 23 20 13 18 25 + 12 13 19 23 23 24 28 16 16 19 28 25 16 19 26 23 27 + 0 28 28 28 26 19 25 0 28 11 24 27 24 16 28 28 19 + 26 19 14 19 23 18 25 18 28 26 25 16 19 27 19 12 25 + 19 27 28 27 12 25 27 25 28 4 23 27 28 23 24 14 11 + + 15 4 10 24 23 24 18 11 22 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 18 24 24 23 24 12 12 12 24 + 24 24 19 24 24 21 24 24 24 24 24 11 21 24 15 21 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 13 18 24 + 24 24 13 10 24 24 22 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 5 24 24 9 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 0 16 20 20 18 15 24 15 23 7 + 20 14 12 12 12 15 18 24 14 23 24 24 23 14 24 24 4 + 10 10 15 23 23 12 14 14 24 21 23 14 14 14 20 16 23 + 1 21 14 24 20 23 14 23 23 18 23 24 12 20 18 21 23 + 11 23 23 12 23 9 13 24 24 12 10 14 10 23 24 15 11 + 21 1 11 23 23 24 15 12 21 1 18 11 12 20 24 12 18 + 11 18 23 15 23 15 14 23 15 23 13 20 14 11 15 12 13 + 24 12 12 12 23 15 14 23 23 23 24 11 18 10 23 13 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 18 23 + 18 24 24 24 23 16 21 18 24 18 18 23 18 10 24 24 15 + 23 12 18 23 12 7 21 5 24 23 20 10 12 23 15 13 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 0 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 0 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 20 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 0 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 0 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 0 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 0 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 0 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 0 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 0 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 0 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 0 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 0 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 18 30 12 30 25 18 20 23 26 24 23 23 15 25 15 + 29 24 24 28 23 27 29 10 20 30 30 28 30 23 15 14 30 + 30 30 20 30 30 20 30 30 30 28 30 16 26 30 15 20 26 + 23 14 24 25 15 29 27 26 30 30 25 28 12 29 14 10 28 + 30 30 23 18 30 30 20 24 30 25 30 15 30 4 30 30 30 + 30 30 30 30 30 20 30 28 20 30 30 30 21 25 30 18 24 + 25 29 21 24 21 24 23 14 30 30 30 30 30 30 30 30 24 + 30 30 11 30 30 30 30 20 15 25 25 11 24 29 24 15 20 + 0 15 15 0 23 12 12 29 24 27 29 28 27 20 29 29 20 + 18 18 20 15 12 15 12 12 28 15 11 12 12 15 20 15 15 + 20 10 12 29 25 15 12 15 27 23 28 28 15 25 11 26 12 + 23 28 27 15 15 20 21 30 28 15 18 15 21 15 29 12 20 + 20 20 16 15 12 28 24 23 15 20 15 23 15 0 29 23 24 + 16 20 28 24 27 12 24 15 24 28 14 25 12 16 12 14 23 + 30 15 15 14 28 20 12 12 28 12 28 16 24 21 11 20 25 + 11 12 15 23 23 25 28 18 18 15 29 26 18 15 27 23 27 + 10 28 29 28 27 15 26 10 29 12 25 27 24 18 28 29 15 + 27 15 15 15 23 20 26 20 29 27 25 18 15 28 15 14 26 + 15 28 28 28 11 25 28 25 29 10 23 28 29 24 24 12 12 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 0 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 0 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 0 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 0 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 0 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 0 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 0 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 0 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 0 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 0 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 15 15 16 21 25 21 11 16 16 12 12 10 12 12 23 12 24 + 20 10 10 18 11 15 20 24 15 21 21 16 21 12 20 21 21 + 21 21 15 21 21 15 21 21 21 18 21 18 12 21 23 15 12 + 11 21 10 11 25 20 14 12 21 21 11 18 26 20 21 24 18 + 21 21 12 16 21 21 16 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 1 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 10 + 21 21 23 21 21 21 21 15 23 12 12 23 1 20 0 25 15 + 24 23 21 20 12 23 23 20 10 14 20 18 14 15 0 20 15 + 16 16 15 25 26 21 23 23 18 24 25 23 23 23 15 23 25 + 15 24 23 20 12 25 23 25 15 12 16 18 20 12 23 12 25 + 12 16 15 20 25 15 14 21 18 21 16 23 14 25 20 23 15 + 15 15 18 25 25 18 0 11 24 15 24 12 21 24 20 11 11 + 18 15 16 2 15 23 10 25 6 16 21 12 23 18 23 21 11 + 21 21 20 21 16 15 23 26 16 26 18 18 11 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 11 15 + 24 18 20 18 14 23 12 24 20 23 11 15 11 16 18 20 23 + 14 21 20 25 12 15 12 15 20 14 12 16 21 16 23 21 12 + 25 16 18 16 25 12 16 12 20 24 12 16 20 10 10 26 23 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 0 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 14 2 10 24 23 24 18 10 21 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 16 24 24 23 24 12 12 12 24 + 24 24 18 24 24 20 24 24 24 24 24 11 21 24 15 20 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 12 18 24 + 24 24 12 10 24 24 21 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 3 24 24 7 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 2 16 20 20 16 15 24 15 23 6 + 20 14 12 12 12 15 16 24 14 23 24 24 23 13 24 24 0 + 10 10 14 23 23 12 14 14 24 21 23 14 14 14 19 16 23 + 3 21 14 24 20 23 14 23 23 16 23 24 12 20 16 21 23 + 11 23 23 12 23 7 12 24 24 12 10 14 10 23 24 15 9 + 20 3 11 23 23 24 15 12 21 3 18 11 12 20 24 12 16 + 11 16 23 15 23 15 14 23 15 23 12 20 14 11 15 12 12 + 24 12 12 12 23 14 14 23 23 23 24 11 16 10 23 12 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 16 23 + 18 24 24 24 23 16 21 18 24 16 18 23 16 10 24 24 15 + 23 12 16 23 12 6 21 3 24 23 20 10 12 23 15 12 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 0 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 0 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 0 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 23 23 23 31 0 31 27 23 23 24 28 26 24 24 16 27 15 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 15 31 28 28 31 31 27 31 10 31 18 12 31 + 31 31 24 23 31 31 23 26 31 27 31 15 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 15 27 27 14 25 31 25 15 23 + 12 16 18 20 24 15 15 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 15 10 16 16 16 23 15 15 + 23 11 16 31 27 15 16 15 29 24 30 31 20 27 14 28 4 + 24 30 29 20 15 23 23 31 31 18 23 16 23 15 31 15 23 + 23 23 21 15 0 31 25 24 15 23 15 24 18 12 31 24 26 + 21 23 30 25 29 15 25 15 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 10 9 15 24 24 27 31 23 23 15 31 28 23 15 28 24 29 + 12 31 31 31 28 15 28 12 31 15 27 29 25 23 31 31 15 + 28 18 20 15 24 23 28 23 31 28 27 23 18 30 15 18 28 + 15 30 31 30 10 27 30 27 31 12 24 30 31 25 26 10 15 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 0 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 0 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 0 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 0 26 14 15 9 7 3 19 11 16 + 14 14 2 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 0 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 21 31 10 31 26 21 23 24 27 25 24 24 15 27 15 + 31 24 24 30 24 28 31 12 23 31 31 29 31 24 18 16 31 + 31 31 23 31 31 23 31 31 31 30 31 20 27 31 15 23 27 + 24 16 24 26 15 31 28 27 31 31 26 30 11 31 16 12 30 + 31 31 24 21 31 31 23 25 31 26 31 15 31 11 31 31 31 + 31 31 31 31 31 23 31 30 23 31 31 31 23 26 31 21 25 + 27 31 23 24 23 24 23 16 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 23 15 27 27 12 25 31 25 15 23 + 11 15 16 18 24 14 14 31 24 28 31 30 28 23 31 31 23 + 21 21 23 15 11 16 15 15 30 0 0 15 15 15 23 15 15 + 23 10 15 31 27 15 15 15 28 23 29 30 18 27 12 27 10 + 23 29 28 18 15 23 23 31 30 16 21 15 23 15 31 14 23 + 23 23 20 15 10 30 25 24 15 23 15 23 16 11 31 24 25 + 20 23 29 25 28 14 24 15 25 29 16 27 15 20 14 16 24 + 31 16 18 16 29 23 15 11 29 11 30 20 24 23 9 23 27 + 0 10 15 24 24 26 30 21 21 15 31 27 21 15 28 24 28 + 12 30 31 30 28 15 27 12 31 14 26 28 25 21 30 31 15 + 28 16 18 15 24 23 27 23 31 28 27 21 16 29 15 16 27 + 15 29 30 29 0 27 29 27 31 12 24 29 31 24 25 11 14 + + 21 21 20 31 15 31 25 20 24 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 23 31 31 31 29 31 18 27 31 12 23 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 15 29 + 31 31 23 20 31 31 24 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 19 24 30 24 11 21 + 15 14 15 16 23 15 19 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 0 0 14 14 14 22 12 11 + 21 5 14 30 26 11 14 11 28 23 28 29 16 26 19 27 19 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 23 21 18 11 15 29 24 24 0 21 11 23 15 15 30 24 25 + 18 21 28 24 28 15 24 11 24 28 15 26 14 18 15 15 24 + 31 15 16 15 28 21 15 12 28 12 29 18 24 23 10 21 26 + 15 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 19 29 30 29 27 12 27 19 30 19 25 28 24 20 29 30 12 + 27 15 19 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 15 26 28 26 30 15 23 28 30 24 25 15 12 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 7 26 14 15 0 7 3 19 11 16 + 14 14 2 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 0 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 0 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 10 11 25 23 25 20 12 24 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 19 25 25 24 25 12 11 12 25 + 25 25 21 25 25 23 25 25 25 24 25 10 23 25 14 23 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 15 16 24 + 25 25 15 10 25 25 24 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 10 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 19 16 24 16 23 10 + 18 12 12 11 12 15 19 24 15 23 24 24 23 16 24 24 10 + 5 9 17 23 23 12 12 12 24 20 21 12 12 12 0 15 23 + 10 20 12 24 21 23 12 23 23 19 24 24 11 21 19 23 23 + 12 24 23 11 23 10 15 25 24 12 10 12 11 23 24 14 12 + 23 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 19 + 10 19 24 16 23 15 15 23 16 24 15 21 12 10 15 12 15 + 25 12 11 12 24 17 15 23 24 23 24 10 19 11 21 15 21 + 21 23 14 14 12 20 24 9 6 15 24 23 5 23 23 19 23 + 19 24 24 24 23 15 23 19 24 19 20 23 19 8 24 24 14 + 23 12 19 23 14 10 23 10 24 23 21 9 12 24 14 15 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 0 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 0 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 0 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 20 31 13 31 25 20 22 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 21 31 31 31 29 31 18 27 31 12 21 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 13 29 + 31 31 23 20 31 31 22 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 18 24 30 24 11 21 + 13 14 15 16 23 13 18 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 1 13 14 14 14 21 12 11 + 21 0 14 30 26 11 14 11 28 23 28 29 16 26 18 27 18 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 21 21 18 11 13 29 24 24 1 21 11 23 15 13 30 24 25 + 18 21 28 24 28 13 24 11 24 28 15 26 14 18 13 15 24 + 31 15 16 15 28 21 14 12 28 12 29 18 24 23 10 21 26 + 13 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 18 29 30 29 27 12 27 18 30 18 25 28 24 20 29 30 12 + 27 15 18 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 13 26 28 26 30 13 23 28 30 24 25 13 12 + + 14 14 12 27 16 27 23 12 21 18 24 23 18 18 3 24 12 + 27 21 21 26 20 25 27 12 16 27 27 25 27 18 11 10 27 + 27 27 18 27 27 20 27 27 27 26 27 12 24 27 10 20 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 12 12 26 + 27 27 18 12 27 27 21 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 16 23 27 23 16 14 + 12 3 10 11 18 12 16 27 21 24 27 26 24 14 27 27 14 + 12 12 14 16 18 10 7 7 26 14 15 9 7 3 19 11 16 + 14 14 0 27 24 16 9 16 25 16 25 26 11 24 16 24 16 + 16 25 25 11 16 14 15 27 26 10 12 3 15 16 27 10 14 + 20 14 12 16 16 26 23 20 14 14 12 16 10 12 27 20 23 + 12 16 25 23 25 12 21 16 23 25 12 24 7 12 12 10 20 + 27 10 11 10 25 14 12 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 16 26 27 26 24 11 24 16 27 16 23 25 23 12 26 27 10 + 24 10 16 16 18 14 24 14 27 24 24 12 10 25 10 12 24 + 16 25 26 25 15 24 25 24 27 12 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 0 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 12 11 26 20 26 23 11 22 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 18 26 26 24 26 15 1 10 26 + 26 26 19 26 26 21 26 26 26 25 26 10 23 26 12 21 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 13 14 25 + 26 26 15 11 26 26 22 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 18 20 25 20 20 12 + 15 11 10 1 15 13 18 25 18 24 25 25 24 14 25 25 12 + 11 11 15 20 21 10 11 11 25 16 18 11 11 11 20 12 20 + 12 16 11 25 0 20 11 20 24 18 24 25 8 23 18 23 20 + 14 24 24 1 20 12 13 26 25 10 11 11 12 20 25 12 12 + 21 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 18 24 20 24 13 18 20 20 24 13 23 11 10 13 10 16 + 26 10 1 10 24 15 13 21 24 21 25 10 18 12 18 13 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 18 24 + 18 25 25 25 24 12 23 18 25 18 23 24 20 11 25 25 12 + 24 10 18 20 15 12 23 12 25 24 23 11 10 24 12 13 23 + 20 24 25 24 18 23 24 23 25 14 15 24 25 18 21 21 12 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 0 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 0 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 10 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 0 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 14 28 14 12 23 24 18 11 12 18 18 24 11 26 + 12 15 15 12 16 10 15 26 23 14 14 11 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 12 14 23 10 14 25 23 10 + 16 24 15 12 28 12 19 10 14 14 12 12 29 15 24 26 12 + 14 14 18 23 14 14 24 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 12 23 14 14 14 21 12 14 23 14 + 11 12 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 12 14 28 23 + 27 24 24 24 18 25 25 12 15 0 12 12 15 23 12 12 23 + 23 23 23 28 29 24 24 24 12 27 28 24 24 24 23 25 28 + 23 27 24 12 12 28 24 28 0 20 11 19 24 11 25 10 28 + 20 15 19 24 28 23 21 19 12 24 23 24 21 28 12 25 23 + 23 23 23 28 28 12 14 16 27 23 26 20 24 27 12 16 19 + 23 23 11 14 10 25 15 28 14 19 24 11 24 23 25 24 16 + 19 24 24 24 11 23 24 29 15 29 19 23 19 21 28 23 11 + 28 28 25 16 18 12 12 23 23 25 12 10 23 28 10 19 15 + 26 12 12 12 15 25 15 26 12 25 12 10 19 23 12 15 25 + 6 24 24 28 18 23 10 23 12 15 11 23 24 11 25 24 10 + 28 19 15 11 28 11 11 11 12 26 18 19 12 15 12 29 25 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 0 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 0 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 0 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 0 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 15 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 0 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 0 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 0 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 0 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 0 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 0 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 0 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 0 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 0 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 4 10 24 23 24 18 11 22 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 18 24 24 23 24 12 12 12 24 + 24 24 19 24 24 21 24 24 24 24 24 11 21 24 15 21 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 13 18 24 + 24 24 13 10 24 24 22 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 5 24 24 9 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 4 16 20 20 18 15 24 15 23 7 + 20 14 12 12 12 15 18 24 14 23 24 24 23 14 24 24 4 + 10 10 15 23 23 12 14 14 24 21 23 14 14 14 20 16 23 + 1 21 14 24 20 23 14 23 23 18 23 24 12 20 18 21 23 + 11 23 23 12 23 0 13 24 24 12 10 14 10 23 24 15 11 + 21 1 11 23 23 24 15 12 21 1 18 11 12 20 24 12 18 + 11 18 23 15 23 15 14 23 15 23 13 20 14 11 15 12 13 + 24 12 12 12 23 15 14 23 23 23 24 11 18 10 23 13 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 18 23 + 18 24 24 24 23 16 21 18 24 18 18 23 18 10 24 24 15 + 23 12 18 23 12 7 21 5 24 23 20 10 12 23 15 13 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 0 33 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 23 23 23 33 15 33 27 23 24 24 28 27 24 24 18 28 14 + 31 25 25 31 25 30 31 14 23 33 33 31 33 24 21 20 33 + 33 33 23 33 33 23 33 33 33 31 33 23 28 33 16 23 28 + 25 20 25 27 10 31 29 28 33 33 27 31 6 31 20 15 31 + 33 33 24 23 33 33 24 27 33 27 33 10 33 12 33 33 33 + 33 33 33 33 33 23 33 31 23 33 33 33 24 27 33 23 26 + 28 31 24 25 24 25 24 20 33 33 33 33 33 33 33 33 25 + 33 33 15 33 33 33 33 23 15 28 28 19 26 31 26 10 23 + 15 18 20 21 24 16 19 31 25 29 31 31 29 23 31 31 23 + 23 23 23 10 6 20 18 18 31 12 15 18 18 18 23 15 10 + 23 12 18 31 28 10 18 10 30 24 31 31 21 28 19 28 19 + 24 31 30 21 10 23 24 0 31 20 23 18 24 10 31 16 23 + 23 23 23 10 15 31 26 25 12 23 14 24 20 15 31 25 27 + 23 23 31 26 30 16 25 10 26 31 20 28 18 23 16 20 25 + 33 20 21 20 31 23 18 10 31 10 31 23 25 24 11 23 28 + 15 10 16 25 24 27 31 23 23 15 31 28 23 10 29 25 30 + 19 31 31 31 29 15 28 19 31 19 27 30 26 23 31 31 16 + 29 20 21 10 24 23 28 23 31 29 28 23 20 31 16 20 28 + 10 31 31 31 15 28 31 28 31 15 24 31 31 25 27 15 16 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 0 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 0 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 0 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 0 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 0 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 0 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 0 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 12 27 16 27 23 12 22 18 24 23 18 18 1 24 12 + 27 21 21 26 20 25 27 12 18 27 27 25 27 18 11 10 27 + 27 27 19 27 27 21 27 27 27 26 27 12 24 27 10 21 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 13 13 26 + 27 27 18 12 27 27 22 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 18 23 27 23 16 14 + 13 1 10 11 18 13 18 27 21 24 27 26 24 14 27 27 14 + 12 12 15 16 18 10 9 9 26 14 15 11 9 1 20 11 16 + 14 14 4 27 24 16 11 16 25 18 25 26 11 24 18 24 18 + 16 25 25 11 16 14 15 27 26 10 12 1 15 16 27 0 14 + 21 14 12 16 16 26 23 20 14 14 12 16 10 13 27 20 23 + 12 18 25 23 25 13 21 16 23 25 13 24 8 12 13 10 20 + 27 10 11 10 25 15 13 18 25 18 26 12 21 15 15 14 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 18 26 27 26 24 11 24 18 27 18 23 25 23 12 26 27 10 + 24 10 18 16 18 14 24 14 27 24 24 12 10 25 10 13 24 + 16 25 26 25 15 24 25 24 27 13 18 25 27 21 23 18 10 + + 14 14 15 23 25 23 12 15 21 11 14 11 11 11 21 12 23 + 21 3 8 20 10 16 21 23 16 23 23 18 23 11 18 20 23 + 23 23 18 23 23 20 23 23 23 20 23 16 14 23 23 20 14 + 10 20 5 12 25 21 16 14 23 23 12 20 25 21 20 23 20 + 23 23 12 15 23 23 21 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 5 12 2 12 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 11 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 19 23 25 + 14 24 21 21 12 25 21 25 16 16 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 0 + 20 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 16 + 16 16 18 10 16 23 8 25 11 18 20 12 21 16 23 20 12 + 23 20 18 20 18 14 21 25 18 25 20 16 16 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 16 16 + 23 20 21 20 15 23 14 23 21 23 12 16 16 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 3 11 25 23 + + 18 18 20 18 27 18 7 20 22 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 18 18 18 14 18 14 23 23 18 + 18 18 19 18 18 21 18 18 18 15 18 21 11 18 24 21 11 + 12 23 12 5 27 16 18 11 18 18 4 15 27 16 23 24 15 + 18 18 14 20 18 18 22 10 18 10 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 7 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 12 12 16 15 13 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 20 24 27 + 18 25 23 16 11 27 23 27 13 18 14 18 23 10 24 11 27 + 15 14 18 23 27 18 16 18 15 23 20 23 16 27 16 24 18 + 0 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 18 + 21 18 14 11 12 24 12 27 12 18 23 10 23 21 24 23 13 + 18 23 23 23 14 18 23 27 14 27 18 21 18 16 26 18 10 + 26 27 24 12 14 9 15 20 20 24 16 11 20 27 12 18 13 + 24 15 16 15 13 24 13 24 16 24 7 12 18 20 15 16 24 + 12 23 23 27 14 18 11 18 16 13 10 20 23 14 24 23 11 + 27 18 15 14 26 10 14 10 16 24 14 18 16 12 10 27 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 0 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 0 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 0 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 15 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 0 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 12 12 14 23 24 23 12 14 12 10 15 15 10 10 20 15 23 + 23 10 10 21 4 18 23 23 12 23 23 20 23 10 16 18 23 + 23 23 12 23 23 12 23 23 23 21 23 15 15 23 21 12 15 + 9 18 10 12 24 23 16 15 23 23 12 21 25 23 18 23 21 + 23 23 10 14 23 23 12 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 15 12 23 14 11 + 14 23 12 10 12 10 15 18 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 10 16 23 21 16 12 23 23 12 + 14 14 12 24 25 18 20 20 21 24 24 20 20 20 12 23 24 + 15 24 20 23 14 24 20 24 18 11 20 21 16 15 23 15 24 + 11 20 18 16 24 12 12 23 21 18 14 20 15 24 23 21 12 + 12 15 15 24 24 0 11 8 24 15 23 15 18 23 23 15 12 + 15 12 20 11 18 21 10 24 11 20 18 14 20 15 21 18 0 + 23 18 16 18 20 12 20 25 20 25 21 15 10 12 24 12 14 + 24 24 21 15 10 12 21 14 14 23 23 15 14 24 16 4 18 + 23 21 23 21 16 23 15 23 23 21 12 18 11 14 21 23 21 + 16 18 16 24 10 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 15 20 23 15 15 25 21 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 0 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 14 14 15 23 25 23 12 15 21 11 14 11 11 11 21 12 23 + 21 3 8 20 10 16 21 23 16 23 23 18 23 11 18 20 23 + 23 23 18 23 23 20 23 23 23 20 23 16 14 23 23 20 14 + 10 20 5 12 25 21 16 14 23 23 12 20 25 21 20 23 20 + 23 23 12 15 23 23 21 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 5 12 2 12 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 11 15 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 19 23 25 + 14 24 21 21 12 25 21 25 16 16 18 20 18 12 23 14 25 + 12 18 16 18 25 14 12 23 20 20 15 21 12 25 21 23 14 + 20 14 16 25 25 20 10 0 24 14 23 12 20 24 21 10 16 + 16 16 18 10 16 23 8 25 11 18 20 12 21 16 23 20 12 + 23 20 18 20 18 14 21 25 18 25 20 16 16 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 16 16 + 23 20 21 20 15 23 14 23 21 23 12 16 16 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 3 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 0 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 0 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 0 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 0 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 12 12 27 18 27 23 12 18 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 13 27 27 25 27 16 10 0 27 + 27 27 15 27 27 17 27 27 27 25 27 11 24 27 11 17 24 + 18 0 20 23 18 26 24 24 27 27 23 25 20 26 9 12 25 + 27 27 16 12 27 27 18 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 0 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 13 21 26 21 18 12 + 14 10 6 10 16 11 13 26 20 24 26 25 24 12 26 26 12 + 12 12 12 18 20 6 10 10 25 15 16 10 10 10 16 12 18 + 12 15 10 26 23 18 10 18 24 15 25 25 10 23 13 24 18 + 15 25 24 10 18 12 14 27 25 6 12 10 14 18 26 11 12 + 17 12 11 18 18 25 21 18 15 12 12 15 0 14 26 18 23 + 11 13 25 21 24 11 20 18 21 25 9 23 10 11 11 0 18 + 27 6 10 0 25 12 10 20 25 20 25 11 20 14 16 12 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 18 24 + 13 25 26 25 24 12 24 13 26 13 23 24 21 12 25 26 11 + 24 6 13 18 16 12 24 12 26 24 23 12 6 25 11 9 24 + 18 25 25 25 16 23 25 23 26 12 16 25 26 20 23 20 11 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 0 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 0 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 0 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 0 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 0 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 0 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 0 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 0 15 23 11 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 11 10 11 24 23 24 16 11 18 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 13 24 24 23 24 11 12 14 24 + 24 24 15 24 24 17 24 24 24 23 24 12 20 24 16 17 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 14 20 23 + 24 24 11 11 24 24 18 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 6 16 24 11 14 + 18 24 4 12 4 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 18 14 24 14 23 10 + 21 15 14 12 11 16 16 24 12 21 24 23 21 10 24 24 10 + 11 11 11 23 24 14 15 15 23 23 23 15 15 15 16 18 23 + 10 23 15 24 18 23 15 23 23 13 23 23 12 18 18 20 23 + 10 23 23 12 23 10 9 24 23 14 11 15 6 23 24 16 10 + 17 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 15 + 12 13 23 14 0 16 12 23 14 23 14 18 15 12 16 14 12 + 24 14 12 14 23 11 15 24 23 24 23 12 13 0 23 10 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 13 23 + 20 23 24 23 21 18 20 20 24 16 16 23 14 11 23 24 16 + 21 14 13 23 11 10 20 10 24 21 18 11 14 23 16 14 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 23 23 23 12 29 12 12 23 24 20 11 14 20 20 25 12 27 + 12 16 16 11 18 10 15 27 23 12 12 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 19 11 12 12 12 11 30 15 24 27 11 + 12 12 20 23 12 12 24 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 15 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 15 21 10 19 24 12 26 11 29 + 21 15 19 24 29 23 23 19 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 19 + 24 23 10 15 0 0 16 29 15 19 24 12 25 24 25 24 18 + 19 24 24 24 10 23 25 30 15 30 19 24 19 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 19 15 + 27 11 12 11 15 26 15 27 12 25 12 0 19 23 11 15 25 + 10 24 24 29 20 23 11 23 12 15 12 23 24 10 25 24 11 + 29 19 15 10 28 12 10 12 12 27 20 19 12 16 14 30 25 + + 17 15 16 21 25 21 11 16 24 12 12 10 12 12 23 12 24 + 20 10 11 18 11 15 20 24 19 21 21 16 21 12 20 21 21 + 21 21 21 21 21 23 21 21 21 18 21 18 12 21 23 23 12 + 11 21 10 11 25 20 19 12 21 21 11 18 26 20 21 24 18 + 21 21 15 16 21 21 24 10 21 11 21 25 21 24 21 21 21 + 21 21 21 21 21 15 21 18 15 21 21 21 14 11 21 16 6 + 12 20 14 10 14 10 12 21 21 21 21 21 21 21 21 21 11 + 21 21 23 21 21 21 21 15 23 12 12 23 6 20 8 25 15 + 24 23 21 20 12 23 23 20 14 14 20 18 15 16 20 20 15 + 16 16 17 25 26 21 23 23 18 24 25 23 23 23 22 23 25 + 15 24 23 20 12 25 23 25 15 19 16 19 20 12 23 12 25 + 12 16 19 20 25 15 15 21 18 21 16 23 14 25 20 23 15 + 23 15 18 25 25 18 8 11 24 15 24 12 21 24 20 11 19 + 18 19 16 5 15 23 0 25 14 19 21 12 23 18 23 21 15 + 21 21 20 21 16 17 23 26 16 26 19 18 19 14 25 15 12 + 25 25 23 11 12 11 18 16 16 23 20 12 16 25 14 19 15 + 24 18 20 18 15 23 15 24 20 23 11 15 19 16 18 20 23 + 14 21 20 25 14 15 12 15 20 15 12 16 21 16 23 21 12 + 25 19 18 16 25 12 16 12 20 24 12 19 20 10 10 26 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 0 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 0 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 0 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 0 23 11 10 15 10 16 + 26 10 0 10 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 0 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 0 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 0 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 17 14 12 27 16 27 23 12 24 18 24 23 18 18 0 24 12 + 27 21 21 26 20 25 27 12 19 27 27 25 27 18 11 10 27 + 27 27 21 27 27 23 27 27 27 26 27 12 24 27 10 23 24 + 20 10 21 23 16 27 24 24 27 27 23 26 18 27 15 15 26 + 27 27 18 12 27 27 24 23 27 23 27 16 27 12 27 27 27 + 27 27 27 27 27 14 27 26 14 27 27 27 15 23 27 12 23 + 24 27 15 21 15 21 16 10 27 27 27 27 27 27 27 27 21 + 27 27 11 27 27 27 27 14 11 24 24 19 23 27 23 16 14 + 15 0 10 11 18 15 19 27 21 24 27 26 24 16 27 27 14 + 12 12 17 16 18 10 10 10 26 14 15 12 10 0 22 11 16 + 14 14 5 27 24 16 12 16 25 19 25 26 11 24 19 24 19 + 16 25 25 11 16 14 15 27 26 10 12 0 15 16 27 10 14 + 23 14 12 16 16 26 23 20 14 14 12 16 10 15 27 20 23 + 12 19 25 23 25 15 21 16 23 25 15 24 10 12 0 10 20 + 27 10 11 10 25 17 15 18 25 18 26 12 21 15 15 15 24 + 15 16 10 20 18 23 26 12 12 11 27 24 12 16 24 20 25 + 19 26 27 26 24 11 24 19 27 19 23 25 23 12 26 27 10 + 24 10 19 16 18 14 24 14 27 24 24 12 10 25 10 15 24 + 16 25 26 25 15 24 25 24 27 15 18 25 27 21 23 18 10 + + 17 10 11 24 23 24 16 12 24 11 20 15 11 11 15 18 20 + 24 12 12 23 12 23 24 20 19 24 24 23 24 11 12 14 24 + 24 24 21 24 24 23 24 24 24 23 24 12 20 24 16 23 20 + 12 14 12 16 23 24 21 20 24 24 16 23 24 24 15 20 23 + 24 24 15 11 24 24 24 15 24 16 24 23 24 21 24 24 24 + 24 24 24 24 24 10 24 23 10 24 24 24 0 16 24 11 14 + 18 24 10 12 10 12 10 14 24 24 24 24 24 24 24 24 12 + 24 24 18 24 24 24 24 10 18 18 18 19 14 24 14 23 10 + 21 15 14 12 11 16 19 24 14 21 24 23 21 16 24 24 10 + 11 11 17 23 24 14 15 15 23 23 23 15 15 15 22 18 23 + 10 23 15 24 18 23 15 23 23 19 23 23 12 18 19 20 23 + 10 23 23 12 23 10 15 24 23 14 11 15 0 23 24 16 12 + 23 10 12 23 23 23 14 12 23 10 20 10 14 21 24 12 19 + 12 19 23 14 23 16 12 23 14 23 15 18 15 12 16 0 15 + 24 14 12 14 23 17 15 24 23 24 23 12 19 6 23 15 18 + 23 23 16 12 11 16 23 11 11 18 24 20 11 23 21 19 23 + 20 23 24 23 21 18 20 20 24 19 16 23 19 11 23 24 16 + 21 14 19 23 14 10 20 10 24 21 18 11 14 23 16 15 20 + 23 23 23 23 23 18 23 18 24 20 11 23 24 12 15 24 16 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 0 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 0 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 0 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 12 14 11 26 20 26 23 11 12 15 23 21 15 15 19 23 19 + 25 18 18 25 16 24 25 14 12 26 26 24 26 15 19 13 26 + 26 26 12 26 26 12 26 26 26 25 26 19 23 26 19 12 23 + 16 13 18 23 20 25 24 23 26 26 23 25 21 25 10 14 25 + 26 26 15 11 26 26 12 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 19 23 26 11 20 + 23 25 12 18 12 18 19 13 26 26 26 26 26 26 26 26 18 + 26 26 13 26 26 26 26 14 19 23 23 12 20 25 20 20 12 + 15 19 19 19 15 12 12 25 18 24 25 25 24 12 25 25 14 + 14 11 12 20 21 19 11 11 25 19 18 11 11 19 12 19 20 + 19 16 14 25 23 20 11 20 24 14 24 25 9 23 12 23 20 + 14 24 24 19 20 12 12 26 25 19 11 19 19 20 25 14 12 + 12 19 19 20 20 25 20 16 19 19 19 19 19 15 25 19 21 + 19 12 24 20 24 12 18 20 20 24 10 23 11 13 12 13 16 + 26 19 0 13 24 12 11 21 24 21 25 10 18 13 18 12 23 + 18 20 19 19 15 23 25 11 12 19 25 23 14 20 24 16 24 + 14 25 25 25 24 19 23 14 25 12 23 24 20 11 25 25 19 + 24 19 0 20 15 12 23 12 25 24 23 11 19 24 19 10 23 + 20 24 25 24 18 23 24 23 25 14 19 24 25 19 21 21 12 + + 17 12 11 26 20 26 23 12 24 15 23 21 15 15 11 23 14 + 25 18 18 25 16 24 25 14 19 26 26 24 26 15 0 10 26 + 26 26 21 26 26 23 26 26 26 25 26 10 23 26 12 23 23 + 16 10 18 23 20 25 24 23 26 26 23 25 21 25 15 15 25 + 26 26 15 11 26 26 24 21 26 23 26 20 26 15 26 26 26 + 26 26 26 26 26 12 26 25 12 26 26 26 12 23 26 11 20 + 23 25 12 18 12 18 14 10 26 26 26 26 26 26 26 26 18 + 26 26 12 26 26 26 26 12 12 23 23 19 20 25 20 20 12 + 15 11 10 0 15 15 19 25 18 24 25 25 24 16 25 25 12 + 11 11 17 20 21 10 11 11 25 16 18 12 11 11 22 12 20 + 12 16 11 25 23 20 12 20 24 19 24 25 10 23 19 23 20 + 14 24 24 0 20 12 15 26 25 10 11 11 12 20 25 12 12 + 23 12 10 20 20 25 20 16 16 12 14 14 10 15 25 16 21 + 10 19 24 20 24 15 18 20 20 24 15 23 11 10 15 10 16 + 26 10 0 0 24 17 15 21 24 21 25 10 19 12 18 15 23 + 18 20 12 16 15 23 25 11 11 12 25 23 11 20 24 19 24 + 19 25 25 25 24 12 23 19 25 19 23 24 20 11 25 25 12 + 24 10 19 20 15 12 23 12 25 24 23 11 10 24 12 15 23 + 20 24 25 24 18 23 24 23 25 15 15 24 25 18 21 21 12 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 0 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 0 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 0 23 23 23 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 15 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 0 24 23 24 10 19 12 20 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 21 21 20 31 15 31 25 20 24 23 27 25 23 23 14 26 11 + 30 24 24 29 24 28 30 11 21 31 31 28 31 23 16 15 31 + 31 31 21 31 31 23 31 31 31 29 31 18 27 31 12 23 27 + 24 15 24 25 11 30 27 27 31 31 25 29 12 30 15 15 29 + 31 31 23 20 31 31 24 25 31 25 31 11 31 10 31 31 31 + 31 31 31 31 31 21 31 29 21 31 31 31 23 25 31 20 24 + 26 30 23 24 23 24 23 15 31 31 31 31 31 31 31 31 24 + 31 31 12 31 31 31 31 21 12 26 26 19 24 30 24 11 21 + 15 14 15 16 23 15 19 30 24 27 30 29 27 21 30 30 21 + 20 20 21 11 12 15 14 14 29 0 15 14 14 14 22 12 11 + 21 5 14 30 26 11 14 11 28 23 28 29 16 26 19 27 19 + 23 28 28 16 11 21 23 31 29 15 20 14 23 11 30 12 21 + 23 21 18 11 15 29 24 24 0 21 11 23 15 15 30 24 25 + 18 21 28 24 28 15 24 11 24 28 15 26 14 18 15 15 24 + 31 15 16 15 28 21 15 12 0 12 29 18 24 23 10 21 26 + 15 11 12 24 23 25 29 20 20 12 30 27 20 11 27 24 28 + 19 29 30 29 27 12 27 19 30 19 25 28 24 20 29 30 12 + 27 15 19 11 23 21 27 21 30 27 26 20 15 28 12 15 27 + 11 28 29 28 15 26 28 26 30 15 23 28 30 24 25 15 12 + + 17 5 11 24 23 24 18 12 24 12 21 16 12 12 14 20 18 + 24 14 14 24 12 23 24 18 19 24 24 23 24 12 12 12 24 + 24 24 21 24 24 23 24 24 24 24 24 11 21 24 15 23 21 + 12 12 14 18 23 24 23 21 24 24 18 24 23 24 15 18 24 + 24 24 15 10 24 24 24 16 24 18 24 23 24 20 24 24 24 + 24 24 24 24 24 6 24 24 10 24 24 24 10 18 24 10 15 + 20 24 10 14 10 14 11 12 24 24 24 24 24 24 24 24 14 + 24 24 16 24 24 24 24 5 16 20 20 19 15 24 15 23 9 + 20 14 12 12 12 15 19 24 14 23 24 24 23 16 24 24 5 + 10 10 17 23 23 12 14 14 24 21 23 14 14 14 22 16 23 + 0 21 14 24 20 23 14 23 23 19 23 24 12 20 19 21 23 + 11 23 23 12 23 10 15 24 24 12 10 14 10 23 24 15 12 + 23 0 11 23 23 24 15 12 21 0 18 11 12 20 24 12 19 + 11 19 23 15 23 15 14 23 15 23 15 20 14 11 15 12 15 + 24 12 12 12 23 17 15 23 23 0 24 11 19 10 23 15 20 + 23 23 15 12 12 18 24 10 10 16 24 21 10 23 23 19 23 + 19 24 24 24 23 16 21 19 24 19 18 23 19 10 24 24 15 + 23 12 19 23 14 9 21 6 24 23 20 10 12 23 15 15 21 + 23 23 24 23 23 20 23 20 24 18 12 23 24 14 16 23 15 + + 18 18 16 29 15 29 24 16 24 23 25 24 23 23 12 25 0 + 28 23 23 28 23 27 28 10 19 29 29 27 29 23 14 12 29 + 29 29 21 29 29 23 29 29 29 28 29 15 25 29 11 23 25 + 23 12 23 24 12 28 26 25 29 29 24 28 14 28 15 15 28 + 29 29 23 16 29 29 24 24 29 24 29 12 29 10 29 29 29 + 29 29 29 29 29 18 29 28 18 29 29 29 20 24 29 16 24 + 25 28 20 23 20 23 21 12 29 29 29 29 29 29 29 29 23 + 29 29 10 29 29 29 29 18 10 25 25 19 24 28 24 12 18 + 15 12 12 14 23 15 19 28 23 26 28 28 26 18 28 28 18 + 16 16 18 12 14 12 12 12 28 11 15 12 12 12 22 10 12 + 18 11 12 28 25 12 12 12 27 21 27 28 14 25 19 25 19 + 21 27 27 14 12 18 20 29 28 12 16 12 20 12 28 11 18 + 23 18 15 12 15 28 24 23 11 18 0 21 12 15 28 23 24 + 15 19 27 24 27 15 23 12 24 27 15 25 12 15 15 12 23 + 29 12 14 12 27 18 15 14 27 14 0 15 23 20 12 18 25 + 15 12 11 23 23 24 28 16 16 10 28 25 16 12 26 23 27 + 19 28 28 28 26 10 25 19 28 19 24 27 24 16 28 28 11 + 26 12 19 12 23 18 25 18 28 26 25 16 12 27 11 15 25 + 12 27 28 27 15 25 27 25 28 15 23 27 28 23 24 15 11 + + 17 11 12 24 24 24 15 12 24 10 18 14 10 10 16 16 21 + 23 12 12 23 11 21 23 21 19 24 24 23 24 10 14 15 24 + 24 24 21 24 24 23 24 24 24 23 24 12 18 24 18 23 18 + 11 15 12 15 24 23 20 18 24 24 15 23 24 23 15 21 23 + 24 24 15 12 24 24 24 14 24 15 24 24 24 23 24 24 24 + 24 24 24 24 24 11 24 23 11 24 24 24 10 15 24 12 12 + 16 23 10 12 10 12 0 15 24 24 24 24 24 24 24 24 12 + 24 24 20 24 24 24 24 11 20 16 16 20 12 23 12 24 11 + 23 16 15 14 10 18 19 23 14 20 23 23 20 16 23 23 11 + 12 12 17 24 24 15 16 16 23 23 23 16 16 16 22 20 24 + 11 23 16 23 16 24 16 24 21 19 23 23 14 16 20 18 24 + 10 23 21 14 24 11 15 24 23 15 12 16 10 24 23 18 12 + 23 11 12 24 24 23 12 11 23 11 21 0 15 23 23 11 19 + 12 19 23 12 21 18 12 24 14 23 15 16 16 12 18 15 15 + 24 15 14 15 23 17 16 24 23 24 23 0 19 10 23 15 16 + 23 24 18 11 10 15 23 12 12 20 23 18 12 24 20 19 21 + 21 23 23 23 20 20 18 21 23 19 15 21 19 12 23 23 18 + 20 15 19 24 14 11 18 11 23 20 16 12 15 23 18 15 18 + 24 23 23 23 23 16 23 16 23 21 10 23 23 12 14 24 18 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 0 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 17 12 14 23 24 23 12 14 24 10 15 12 10 10 20 14 23 + 23 10 11 21 10 18 23 23 19 23 23 20 23 10 16 18 23 + 23 23 21 23 23 23 23 23 23 21 23 15 15 23 21 23 15 + 5 18 10 12 24 23 19 15 23 23 12 21 25 23 18 23 21 + 23 23 15 14 23 23 24 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 14 16 23 21 16 16 23 23 12 + 14 14 17 24 25 18 20 20 21 24 24 20 20 20 22 23 24 + 12 24 20 23 14 24 20 24 18 19 20 21 16 14 23 15 24 + 11 20 19 16 24 12 15 23 21 18 14 20 12 24 23 21 12 + 23 12 15 24 24 21 11 6 24 12 23 11 18 23 23 0 19 + 15 19 20 11 18 21 11 24 14 20 18 14 20 15 21 18 15 + 23 18 16 18 20 17 20 25 20 25 21 15 19 0 24 15 14 + 24 24 21 0 10 12 21 14 14 23 23 15 14 24 16 19 18 + 23 21 23 21 16 23 15 23 23 21 12 18 19 14 21 23 21 + 16 18 19 24 14 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 17 11 11 25 21 25 21 12 24 14 23 20 14 14 12 23 15 + 25 16 16 24 15 24 25 15 19 25 25 24 25 14 10 11 25 + 25 25 21 25 25 23 25 25 25 24 25 0 23 25 12 23 23 + 15 11 16 21 21 25 23 23 25 25 21 24 23 25 15 15 24 + 25 25 15 10 25 25 24 20 25 21 25 21 25 16 25 25 25 + 25 25 25 25 25 11 25 24 11 25 25 25 12 21 25 10 18 + 23 25 12 16 12 16 12 11 25 25 25 25 25 25 25 25 16 + 25 25 14 25 25 25 25 11 14 23 23 19 18 25 18 21 11 + 16 12 11 10 14 15 19 25 16 23 25 24 23 16 25 25 11 + 10 10 17 21 23 11 12 12 24 18 20 12 12 12 22 14 21 + 11 18 12 25 23 21 12 21 24 19 24 24 10 23 19 23 21 + 12 24 24 10 21 11 15 25 24 11 10 12 12 21 25 12 12 + 23 11 0 21 21 24 18 15 18 11 15 12 11 16 25 15 20 + 0 19 24 18 24 15 16 21 18 24 15 23 12 6 15 11 15 + 25 11 10 11 24 17 15 23 24 23 24 10 19 12 0 15 23 + 20 21 12 15 14 21 24 10 10 14 25 23 10 21 23 19 24 + 19 24 25 24 23 14 23 19 25 19 21 24 19 10 24 25 12 + 23 11 19 21 14 11 23 11 25 23 23 10 11 24 12 15 23 + 21 24 24 24 20 23 24 23 25 15 14 24 25 16 20 23 12 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 0 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 0 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 0 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 0 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 12 11 27 21 19 11 18 15 31 26 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 0 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 0 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 0 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 0 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 12 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 0 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 0 5 15 24 23 4 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 0 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 5 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 0 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 0 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 0 21 27 11 19 15 + 25 14 15 14 15 24 15 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 15 10 10 25 23 25 20 11 22 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 18 25 25 24 25 12 11 12 25 + 25 25 19 25 25 21 25 25 25 24 25 10 23 25 14 21 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 13 16 24 + 25 25 13 9 25 25 22 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 9 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 18 16 24 16 23 10 + 18 12 12 11 12 14 18 24 15 23 24 24 23 14 24 24 10 + 4 7 15 23 23 12 12 12 24 20 21 12 12 12 20 15 23 + 10 20 12 24 21 23 12 23 23 18 24 24 11 21 18 23 23 + 12 24 23 11 23 10 13 25 24 12 9 12 11 23 24 14 11 + 21 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 18 24 16 23 14 15 23 16 24 13 21 12 10 14 12 14 + 25 12 11 12 24 15 13 23 24 23 24 10 18 11 21 13 21 + 21 23 14 14 12 20 24 7 5 15 24 23 0 23 23 18 23 + 18 24 24 24 23 15 23 18 24 18 20 23 18 6 24 24 14 + 23 12 18 23 12 10 23 10 24 23 21 7 12 24 14 13 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 0 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 0 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 17 12 14 23 24 23 12 14 24 10 15 12 10 10 20 14 23 + 23 10 11 21 10 18 23 23 19 23 23 20 23 10 16 18 23 + 23 23 21 23 23 23 23 23 23 21 23 15 15 23 21 23 15 + 5 18 10 12 24 23 19 15 23 23 12 21 25 23 18 23 21 + 23 23 15 14 23 23 24 12 23 12 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 21 12 23 23 23 12 12 23 14 11 + 14 23 12 10 12 10 11 18 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 12 23 14 14 23 11 23 11 24 12 + 23 20 18 16 10 21 21 23 14 16 23 21 16 16 23 23 12 + 14 14 17 24 25 18 20 20 21 24 24 20 20 20 22 23 24 + 12 24 20 23 14 24 20 24 18 19 20 21 16 14 23 15 24 + 11 20 19 16 24 12 15 23 21 18 14 20 12 24 23 21 12 + 23 12 15 24 24 21 11 6 24 12 23 11 18 23 23 0 19 + 15 19 20 11 18 21 11 24 14 20 18 14 20 15 21 18 15 + 23 18 16 18 20 17 20 25 20 25 21 15 19 12 24 15 14 + 24 24 21 0 10 12 21 14 14 23 23 15 14 24 16 0 18 + 23 21 23 21 16 23 15 23 23 21 12 18 19 14 21 23 21 + 16 18 19 24 14 12 15 12 23 16 14 14 18 20 21 18 15 + 24 20 21 20 24 14 20 14 23 23 10 20 23 10 12 25 21 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 0 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 0 27 28 27 25 0 25 19 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 0 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 0 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 6 21 21 10 23 12 9 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 6 13 14 10 10 16 10 31 9 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 6 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 6 20 31 24 + 29 27 26 25 23 27 27 6 21 12 6 10 12 24 6 0 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 6 15 31 27 31 12 23 11 13 25 15 28 14 31 + 23 11 13 25 31 24 24 13 10 26 24 27 24 31 6 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 6 23 18 + 25 24 11 20 12 27 21 31 20 13 26 15 27 25 27 26 23 + 13 26 25 26 11 24 27 31 11 31 13 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 6 14 24 31 12 23 12 + 28 10 0 0 12 28 14 28 6 27 16 12 20 24 10 9 27 + 12 26 25 31 23 24 14 24 6 12 15 24 26 11 27 26 14 + 31 13 10 11 31 15 11 15 6 28 23 13 6 21 18 31 27 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 0 27 15 28 10 27 15 11 19 24 0 15 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 0 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 20 20 21 16 27 16 10 21 24 15 11 11 15 15 24 0 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 21 16 16 23 16 16 16 14 16 23 10 16 24 23 10 + 14 23 12 10 27 15 19 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 24 11 16 11 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 6 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 5 9 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 14 11 15 14 15 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 22 24 27 + 20 26 24 15 12 27 24 27 15 19 12 19 23 0 24 10 27 + 16 15 19 23 27 20 18 19 14 23 21 24 18 27 15 24 20 + 23 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 19 + 23 20 12 12 12 24 12 27 14 19 23 6 24 23 24 23 15 + 19 23 23 23 12 20 24 28 15 28 19 23 19 18 27 20 10 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 19 15 + 25 14 15 14 15 24 0 25 15 24 10 12 19 21 14 15 24 + 11 23 23 27 15 20 10 20 15 15 9 21 23 12 24 23 10 + 27 19 15 12 27 8 12 6 15 25 15 19 15 12 11 28 24 + + 17 16 15 28 15 28 24 15 24 21 25 24 21 21 11 24 10 + 28 23 23 27 23 26 28 10 19 28 28 27 28 21 12 12 28 + 28 28 21 28 28 23 28 28 28 27 28 14 25 28 10 23 25 + 23 12 23 24 14 28 25 25 28 28 24 27 15 28 15 15 27 + 28 28 21 15 28 28 24 24 28 24 28 14 28 11 28 28 28 + 28 28 28 28 28 16 28 27 16 28 28 28 18 24 28 15 23 + 24 28 18 23 18 23 20 12 28 28 28 28 28 28 28 28 23 + 28 28 6 28 28 28 28 16 0 24 24 19 23 28 23 14 16 + 15 11 12 12 21 15 19 28 23 25 28 27 25 16 28 28 16 + 15 15 17 14 15 12 11 11 27 12 15 12 11 11 22 0 14 + 16 12 11 28 24 14 12 14 26 20 27 27 12 24 19 25 19 + 20 27 26 12 14 16 18 28 27 12 15 11 18 14 28 10 16 + 23 16 14 14 15 27 23 23 12 16 10 20 12 15 28 23 24 + 14 19 27 23 26 15 23 14 23 27 15 24 11 14 15 12 23 + 28 12 12 12 27 17 15 15 27 15 27 14 23 18 12 16 24 + 15 14 10 23 21 24 27 15 15 0 28 25 15 14 25 23 26 + 19 27 28 27 25 0 25 0 28 19 24 26 23 15 27 28 10 + 25 12 19 14 21 16 25 16 28 25 24 15 12 27 10 15 25 + 14 27 27 27 15 24 27 24 28 15 21 27 28 23 24 15 10 + + 14 14 15 23 25 23 12 15 14 14 14 19 12 12 21 19 23 + 21 12 8 20 10 16 21 23 14 23 23 19 23 11 19 20 23 + 23 23 14 23 23 14 23 23 23 20 23 19 19 23 23 14 14 + 14 20 11 12 25 21 15 14 23 23 14 20 25 21 20 23 20 + 23 23 11 15 23 23 14 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 19 12 23 15 12 + 12 21 12 11 12 14 19 20 23 23 23 23 23 23 23 23 8 + 23 23 23 23 23 23 23 14 23 14 12 23 12 21 11 25 14 + 24 21 20 19 11 23 23 21 5 19 21 20 15 14 21 21 14 + 15 15 14 25 25 20 21 21 20 24 24 21 21 21 14 23 25 + 19 24 21 21 12 25 21 25 16 12 18 20 18 19 23 14 25 + 12 18 16 19 25 14 12 23 20 20 15 21 19 25 21 23 14 + 14 19 19 25 25 20 11 12 24 19 23 19 20 24 21 19 11 + 19 14 19 14 19 23 8 25 10 18 20 13 21 16 23 20 10 + 23 20 19 20 19 14 21 25 18 25 20 16 0 13 24 14 12 + 24 25 23 19 14 12 20 15 15 23 21 14 15 25 15 10 16 + 23 20 21 20 15 23 14 23 0 23 12 19 10 15 20 21 23 + 15 20 18 25 11 14 14 14 21 15 12 15 20 18 23 20 19 + 25 18 20 19 24 12 19 13 21 23 19 18 21 19 19 25 23 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 0 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 15 14 15 23 25 23 12 15 22 11 14 11 11 11 21 12 23 + 21 5 10 20 10 16 21 23 18 23 23 18 23 11 18 20 23 + 23 23 19 23 23 21 23 23 23 20 23 16 14 23 23 21 14 + 10 20 6 12 25 21 18 14 23 23 12 20 25 21 20 23 20 + 23 23 13 15 23 23 22 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 6 12 4 12 20 23 23 23 23 23 23 23 23 10 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 12 15 21 20 15 14 21 21 14 + 15 15 15 25 25 20 21 21 20 24 24 21 21 21 20 23 25 + 14 24 21 21 12 25 21 25 16 18 18 20 18 12 23 14 25 + 12 18 18 18 25 14 13 23 20 20 15 21 12 25 21 23 14 + 21 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 18 + 16 18 18 10 16 23 10 25 12 18 20 12 21 16 23 20 13 + 23 20 18 20 18 15 21 25 18 25 20 16 18 12 24 14 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 18 16 + 23 20 21 20 15 23 14 23 21 23 0 16 18 15 20 21 23 + 15 20 18 25 12 14 14 14 21 15 12 15 20 18 23 20 14 + 25 18 20 18 24 12 18 12 21 23 11 18 21 1 11 25 23 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 0 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 12 29 12 12 23 24 20 11 14 20 20 25 12 27 + 12 16 16 11 18 10 15 27 23 12 12 10 12 20 24 24 12 + 12 12 23 12 12 23 12 12 12 11 12 24 11 12 25 23 11 + 18 24 16 12 29 12 19 11 12 12 12 11 30 15 24 27 11 + 12 12 20 23 12 12 24 14 12 12 12 29 12 27 12 12 12 + 12 12 12 12 12 23 12 11 23 12 12 12 23 12 12 23 15 + 12 12 23 16 23 16 21 24 12 12 12 12 12 12 12 12 16 + 12 12 26 12 12 12 12 23 26 12 12 26 15 12 15 29 23 + 27 25 24 24 20 25 25 12 16 10 12 11 15 23 12 12 23 + 23 23 23 29 30 24 25 25 11 28 28 25 25 25 23 26 29 + 23 28 25 12 12 29 25 29 15 21 10 19 24 12 26 11 29 + 21 15 19 24 29 23 23 19 11 24 23 25 23 29 12 25 23 + 23 23 24 29 29 11 15 18 28 23 27 21 24 27 12 18 19 + 24 23 10 15 0 25 16 29 15 19 24 12 25 24 25 24 18 + 19 24 24 24 10 23 25 30 15 30 19 24 19 23 28 23 12 + 28 29 25 18 20 12 11 23 23 26 12 11 23 29 10 19 15 + 27 11 12 11 15 26 15 27 12 25 12 0 0 23 11 15 25 + 10 24 24 29 20 23 11 23 12 15 12 23 24 10 25 24 11 + 29 19 15 10 28 12 10 12 12 27 20 19 12 16 14 30 25 + + 14 10 8 25 23 25 20 9 21 12 23 18 12 12 12 21 16 + 24 15 15 24 14 23 24 16 16 25 25 24 25 12 11 12 25 + 25 25 18 25 25 20 25 25 25 24 25 10 23 25 14 20 23 + 14 12 15 20 23 24 23 23 25 25 20 24 23 24 12 16 24 + 25 25 12 7 25 25 21 18 25 20 25 23 25 18 25 25 25 + 25 25 25 25 25 10 25 24 10 25 25 25 11 20 25 7 16 + 21 24 11 15 11 15 12 12 25 25 25 25 25 25 25 25 15 + 25 25 15 25 25 25 25 10 15 21 21 16 16 24 16 23 10 + 18 12 12 11 12 14 16 24 15 23 24 24 23 13 24 24 10 + 2 6 14 23 23 12 12 12 24 20 21 12 12 12 19 15 23 + 10 20 12 24 21 23 12 23 23 16 24 24 11 21 16 23 23 + 12 24 23 11 23 10 12 25 24 12 7 12 11 23 24 14 10 + 20 10 10 23 23 24 16 14 20 10 16 12 12 18 24 14 18 + 10 16 24 16 23 14 15 23 16 24 12 21 12 10 14 12 14 + 25 12 11 12 24 14 12 23 24 23 24 10 16 11 21 12 21 + 21 23 14 14 12 20 24 6 3 15 24 23 2 23 23 16 23 + 16 24 24 24 23 15 23 16 24 16 20 23 16 0 24 24 14 + 23 12 16 23 12 10 23 10 24 23 21 6 12 24 14 12 23 + 23 24 24 24 21 21 24 21 24 16 12 24 24 15 18 23 14 + + 23 23 23 14 28 14 12 23 23 18 10 15 18 18 24 15 26 + 15 15 15 15 16 10 12 26 23 14 14 15 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 23 15 14 25 23 10 + 16 24 15 12 28 15 4 10 14 14 12 15 29 12 24 26 12 + 14 14 18 23 14 14 23 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 21 12 14 23 14 + 11 15 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 15 14 28 23 + 27 24 24 24 18 25 25 15 15 15 15 15 0 23 15 12 23 + 23 23 23 28 29 24 24 24 15 27 28 24 24 24 23 25 28 + 23 27 24 15 11 28 24 28 10 20 11 12 24 15 25 10 28 + 20 11 10 24 28 23 21 14 15 24 23 24 21 28 15 25 23 + 23 23 23 28 28 15 14 16 27 23 26 20 24 27 15 16 12 + 23 23 15 14 15 25 15 28 14 11 24 11 24 23 25 24 16 + 14 24 24 24 15 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 16 18 12 15 23 23 25 15 10 23 28 4 16 10 + 26 12 12 15 0 25 10 26 15 25 12 15 14 23 0 12 25 + 9 24 24 28 18 23 10 23 15 0 11 23 24 11 25 24 15 + 28 11 12 15 28 11 15 11 15 26 18 11 15 15 15 29 25 + + 24 24 24 11 31 11 15 24 24 23 12 16 23 23 26 14 28 + 10 20 20 0 21 11 15 28 24 11 11 10 11 23 25 25 11 + 11 11 24 11 11 24 11 11 11 0 11 24 12 11 27 24 12 + 21 25 20 15 31 10 19 12 11 11 15 0 31 15 25 28 6 + 11 11 23 24 11 11 24 16 11 15 11 31 11 28 11 11 11 + 11 11 11 11 11 24 11 0 24 11 11 11 23 15 11 24 18 + 14 10 23 20 23 20 23 25 11 11 11 11 11 11 11 11 20 + 11 11 27 11 11 11 11 24 27 14 14 27 18 10 18 31 24 + 28 26 25 25 23 27 27 10 20 12 10 0 15 24 10 10 24 + 24 24 24 31 31 25 26 26 0 29 30 26 26 26 24 27 31 + 24 29 26 10 14 31 26 31 15 23 10 19 25 14 27 12 31 + 23 15 19 25 31 24 23 19 0 25 24 26 23 31 10 27 24 + 24 24 24 31 31 0 18 21 29 24 28 23 25 28 10 21 19 + 24 24 10 18 11 27 20 31 18 19 25 14 26 24 27 25 21 + 19 25 25 25 10 24 26 31 15 31 19 24 20 23 30 24 14 + 30 31 27 21 23 15 0 24 24 27 10 12 24 31 12 21 15 + 28 10 10 0 15 27 15 28 10 27 15 11 19 24 0 0 27 + 12 25 25 31 23 24 12 24 10 15 14 24 25 10 27 25 12 + 31 19 15 10 30 14 10 14 10 28 23 19 10 20 16 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 0 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 0 11 19 15 20 15 24 15 27 25 24 14 11 26 0 15 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 15 15 14 28 15 28 24 14 15 20 24 23 20 20 15 24 15 + 27 23 23 27 21 25 27 11 15 28 28 26 28 20 15 11 28 + 28 28 15 28 28 15 28 28 28 27 28 15 24 28 15 15 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 11 11 27 + 28 28 20 14 28 28 15 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 15 24 24 10 23 27 23 15 15 + 12 15 15 15 20 0 4 27 23 25 27 27 25 15 27 27 15 + 14 14 15 15 16 15 10 10 27 15 14 10 10 15 15 15 15 + 15 12 10 27 24 15 10 15 25 18 26 27 12 24 10 24 15 + 18 26 25 15 15 15 16 28 27 15 14 15 16 15 27 9 15 + 15 15 15 15 15 27 23 21 15 15 15 18 15 12 27 21 23 + 15 15 26 23 25 0 23 15 23 26 11 24 10 12 0 11 21 + 28 15 15 11 26 15 10 16 26 16 27 12 23 16 14 15 24 + 14 15 15 21 20 24 27 14 14 15 27 24 14 15 25 21 25 + 11 27 27 27 25 15 24 11 27 4 24 25 23 14 27 27 15 + 25 0 12 15 20 15 24 15 27 25 24 14 15 26 15 11 24 + 15 26 27 26 14 24 26 24 27 11 20 26 27 23 23 16 4 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 0 18 16 12 24 12 26 24 23 12 0 25 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 0 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 0 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 31 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 0 10 20 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 20 20 21 16 27 16 10 21 22 15 10 11 15 15 24 1 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 21 16 16 16 14 16 23 10 16 24 21 10 + 14 23 12 10 27 15 18 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 22 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 5 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 4 7 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 13 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 11 27 24 27 13 18 12 18 23 1 24 10 27 + 16 13 18 23 27 20 18 18 14 23 21 24 18 27 15 24 20 + 21 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 18 + 23 20 12 12 12 24 12 27 12 18 23 4 24 23 24 23 14 + 18 23 23 23 12 20 24 28 13 28 18 23 18 18 27 20 8 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 18 13 + 25 14 15 14 13 24 13 25 15 24 10 12 18 21 14 15 24 + 11 23 23 27 15 20 0 20 15 13 7 21 23 12 24 23 10 + 27 18 14 12 27 6 12 4 15 25 15 18 15 12 11 28 24 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 0 15 12 6 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 0 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 0 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 28 23 19 0 21 18 31 27 + + 20 20 21 16 27 16 10 21 21 15 10 11 15 15 24 3 25 + 15 12 12 14 14 12 15 25 20 16 16 12 16 15 23 23 16 + 16 16 20 16 16 20 16 16 16 14 16 23 10 16 24 20 10 + 14 23 12 10 27 15 16 10 16 16 10 14 28 15 23 25 14 + 16 16 15 21 16 16 21 11 16 10 16 27 16 25 16 16 16 + 16 16 16 16 16 20 16 14 20 16 16 16 18 10 16 21 12 + 3 15 18 12 18 12 16 23 16 16 16 16 16 16 16 16 12 + 16 16 24 16 16 16 16 20 24 2 6 24 12 15 12 27 20 + 25 24 23 23 15 24 24 15 12 11 15 14 12 20 15 15 20 + 21 21 20 27 28 23 24 24 14 26 27 24 24 24 20 24 27 + 20 26 24 15 9 27 24 27 12 16 12 16 23 3 24 10 27 + 16 12 16 23 27 20 18 16 14 23 21 24 18 27 15 24 20 + 20 20 23 27 27 14 12 14 26 20 25 16 23 25 15 14 16 + 23 20 12 12 12 24 12 27 12 16 23 3 24 23 24 23 14 + 16 23 23 23 12 20 24 28 12 28 16 23 16 18 27 20 7 + 27 27 24 14 15 10 14 21 21 24 15 10 21 27 11 16 12 + 25 14 15 14 12 24 12 25 15 24 10 12 16 21 14 15 24 + 11 23 23 27 15 20 10 20 15 12 0 21 23 12 24 23 10 + 27 16 14 12 27 5 12 3 15 25 15 16 15 12 11 28 24 + + 18 18 20 18 27 18 9 20 24 14 11 10 14 14 23 10 24 + 16 12 12 15 12 12 16 24 19 18 18 14 18 14 23 23 18 + 18 18 21 18 18 23 18 18 18 15 18 21 11 18 24 23 11 + 12 23 12 6 27 16 19 11 18 18 5 15 27 16 23 24 15 + 18 18 15 20 18 18 24 10 18 11 18 27 18 25 18 18 18 + 18 18 18 18 18 18 18 15 18 18 18 18 16 9 18 20 11 + 10 16 16 12 16 12 15 23 18 18 18 18 18 18 18 18 12 + 18 18 24 18 18 18 18 18 24 10 10 24 11 16 11 27 18 + 25 23 23 23 14 24 24 16 14 12 16 15 15 18 16 16 18 + 20 20 18 27 27 23 23 23 15 25 26 23 23 23 22 24 27 + 18 25 23 16 12 27 23 27 15 19 14 19 23 10 24 11 27 + 15 15 19 23 27 18 16 19 15 23 20 23 16 27 16 24 18 + 23 18 21 27 27 15 11 12 25 18 24 15 23 25 16 12 19 + 21 19 14 11 12 24 12 27 14 19 23 10 23 21 24 23 15 + 19 23 23 23 14 18 23 27 15 27 19 21 19 16 26 18 10 + 26 27 24 12 14 10 15 20 20 24 16 11 20 27 12 19 15 + 24 15 16 15 15 24 15 24 16 24 9 12 19 20 15 16 24 + 12 23 23 27 14 18 11 18 16 15 10 0 23 14 24 23 11 + 27 19 15 14 26 10 14 10 16 24 14 19 16 12 10 27 24 + + 20 20 18 30 12 30 25 18 20 23 26 24 23 23 15 25 15 + 29 24 24 28 23 27 29 10 20 30 30 28 30 23 15 14 30 + 30 30 20 30 30 20 30 30 30 28 30 16 26 30 15 20 26 + 23 14 24 25 15 29 27 26 30 30 25 28 12 29 14 10 28 + 30 30 23 18 30 30 20 24 30 25 30 15 30 4 30 30 30 + 30 30 30 30 30 20 30 28 20 30 30 30 21 25 30 18 24 + 25 29 21 24 21 24 23 14 30 30 30 30 30 30 30 30 24 + 30 30 11 30 30 30 30 20 15 25 25 11 24 29 24 15 20 + 0 15 15 15 23 12 12 29 24 27 29 28 27 20 29 29 20 + 18 18 20 15 12 15 12 12 28 15 11 12 12 15 20 15 15 + 20 10 12 29 25 15 12 15 27 23 28 28 15 25 11 26 12 + 23 28 27 15 15 20 21 30 28 15 18 15 21 15 29 12 20 + 20 20 16 15 12 28 24 23 15 20 15 23 15 0 29 23 24 + 16 20 28 24 27 12 24 15 24 28 14 25 12 16 12 14 23 + 30 15 15 14 28 20 12 12 28 12 28 16 24 21 11 20 25 + 11 12 15 23 23 25 28 18 18 15 29 26 18 15 27 23 27 + 10 28 29 28 27 15 26 10 29 12 25 27 24 18 28 29 15 + 27 15 15 15 23 20 26 20 29 27 25 18 0 28 15 14 26 + 15 28 28 28 11 25 28 25 29 10 23 28 29 24 24 12 12 + + 17 12 12 27 18 27 23 12 24 16 24 23 16 16 10 23 12 + 26 20 20 25 18 24 26 12 19 27 27 25 27 16 10 6 27 + 27 27 21 27 27 23 27 27 27 25 27 11 24 27 11 23 24 + 18 6 20 23 18 26 24 24 27 27 23 25 20 26 15 15 25 + 27 27 16 12 27 27 24 23 27 23 27 18 27 14 27 27 27 + 27 27 27 27 27 12 27 25 12 27 27 27 14 23 27 12 21 + 23 26 14 20 14 20 15 6 27 27 27 27 27 27 27 27 20 + 27 27 12 27 27 27 27 12 12 23 23 19 21 26 21 18 12 + 15 10 0 10 16 15 19 26 20 24 26 25 24 16 26 26 12 + 12 12 17 18 20 0 10 10 25 15 16 12 10 10 22 12 18 + 12 15 10 26 23 18 12 18 24 19 25 25 10 23 19 24 19 + 15 25 24 10 18 12 15 27 25 0 12 10 14 18 26 11 12 + 23 12 11 18 18 25 21 18 15 12 12 15 0 15 26 18 23 + 11 19 25 21 24 15 20 18 21 25 15 23 10 11 15 6 18 + 27 0 10 6 25 17 15 20 25 20 25 11 20 14 16 15 23 + 16 18 11 18 16 23 25 12 12 12 26 24 12 18 24 19 24 + 19 25 26 25 24 12 24 19 26 19 23 24 21 12 25 26 11 + 24 0 19 18 16 12 24 12 26 24 23 12 0 0 11 15 24 + 18 25 25 25 16 23 25 23 26 15 16 25 26 20 23 20 11 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 0 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 17 15 14 28 15 28 24 14 24 20 24 23 20 20 10 24 11 + 27 23 23 27 21 25 27 11 19 28 28 26 28 20 12 11 28 + 28 28 21 28 28 23 28 28 28 27 28 12 24 28 0 23 24 + 21 11 23 24 15 27 25 24 28 28 24 27 16 27 15 15 27 + 28 28 20 14 28 28 24 23 28 24 28 15 28 12 28 28 28 + 28 28 28 28 28 15 28 27 15 28 28 28 16 24 28 14 23 + 24 27 16 23 16 23 18 11 28 28 28 28 28 28 28 28 23 + 28 28 10 28 28 28 28 15 10 24 24 19 23 27 23 15 15 + 15 10 11 12 20 15 19 27 23 25 27 27 25 16 27 27 15 + 14 14 17 15 16 11 10 10 27 12 15 12 10 10 22 10 15 + 15 12 10 27 24 15 12 15 25 19 26 27 12 24 19 24 19 + 18 26 25 12 15 15 16 28 27 11 14 10 16 15 27 5 15 + 23 15 12 15 15 27 23 21 12 15 11 18 11 15 27 21 23 + 12 19 26 23 25 15 23 15 23 26 15 24 10 12 15 11 21 + 28 11 12 11 26 17 15 16 26 16 27 12 23 16 14 15 24 + 15 15 0 21 20 24 27 14 14 10 27 24 14 15 25 21 25 + 19 27 27 27 25 10 24 19 27 19 24 25 23 14 27 27 0 + 25 11 19 15 20 15 24 15 27 25 24 14 11 26 0 0 24 + 15 26 27 26 15 24 26 24 27 15 20 26 27 23 23 16 10 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 0 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 0 18 14 12 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 0 15 12 27 10 12 10 14 25 16 19 14 14 12 28 24 + + 23 23 23 31 15 31 27 23 24 24 28 26 24 24 16 27 12 + 31 25 25 31 24 29 31 12 23 31 31 30 31 24 20 18 31 + 31 31 23 31 31 23 31 31 31 31 31 21 28 31 15 23 28 + 24 18 25 27 0 31 28 28 31 31 27 31 10 31 18 15 31 + 31 31 24 23 31 31 24 26 31 27 31 0 31 12 31 31 31 + 31 31 31 31 31 23 31 31 23 31 31 31 23 27 31 23 25 + 27 31 23 25 23 25 24 18 31 31 31 31 31 31 31 31 25 + 31 31 14 31 31 31 31 23 14 27 27 19 25 31 25 0 23 + 15 16 18 20 24 15 19 31 25 28 31 31 28 23 31 31 23 + 23 23 23 0 10 18 16 16 31 11 15 16 16 16 23 14 0 + 23 11 16 31 27 0 16 0 29 24 30 31 20 27 19 28 19 + 24 30 29 20 0 23 23 31 31 18 23 16 23 0 31 15 23 + 23 23 21 0 15 31 25 24 11 23 12 24 18 15 31 24 26 + 21 23 30 25 29 15 25 0 25 30 18 27 16 21 15 18 24 + 31 18 20 18 30 23 16 10 30 10 31 21 25 23 10 23 27 + 15 6 15 24 24 27 31 23 23 14 31 28 23 0 28 24 29 + 19 31 31 31 28 14 28 19 31 19 27 29 25 23 31 31 15 + 28 18 20 0 24 23 28 23 31 28 27 23 18 30 15 18 28 + 0 30 0 30 15 27 30 27 31 15 24 30 31 25 26 15 15 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 0 31 16 12 16 10 29 23 18 10 23 20 33 28 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 0 12 0 12 11 27 21 19 11 18 15 31 26 + + 21 21 23 15 28 15 11 23 24 16 11 12 16 16 24 10 25 + 14 14 14 12 15 11 15 25 21 15 15 12 15 16 23 24 15 + 15 15 21 15 15 23 15 15 15 12 15 23 0 15 24 23 9 + 15 24 14 11 28 14 19 10 15 15 11 12 28 15 24 25 12 + 15 15 16 23 15 15 24 12 15 11 15 28 15 26 15 15 15 + 15 15 15 15 15 21 15 12 21 15 15 15 20 11 15 23 12 + 10 14 20 14 20 14 18 24 15 15 15 15 15 15 15 15 14 + 15 15 25 15 15 15 15 21 25 10 10 25 12 14 12 28 21 + 26 24 24 23 16 24 24 14 14 10 14 12 15 21 14 14 21 + 23 23 21 28 28 24 24 24 12 27 27 24 24 24 22 25 28 + 21 27 24 14 12 28 24 28 15 19 12 19 23 10 25 6 28 + 18 15 19 23 28 21 20 19 12 24 23 24 20 28 14 24 21 + 23 21 23 28 28 12 12 15 27 21 25 18 24 26 14 15 19 + 23 21 12 12 11 24 14 28 14 19 24 10 24 23 24 24 15 + 19 24 23 24 12 21 24 28 15 28 19 23 19 20 27 21 10 + 27 28 24 15 16 11 12 23 23 25 14 9 23 28 10 19 15 + 25 12 14 12 15 25 15 25 14 24 11 11 19 23 12 15 24 + 10 24 23 28 16 21 9 21 14 15 10 23 24 12 24 24 0 + 28 19 15 12 27 0 12 10 14 25 16 19 14 14 12 28 24 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 0 16 10 29 23 18 10 23 20 33 28 + + 23 23 24 12 30 12 14 24 24 21 12 15 21 21 25 12 27 + 11 18 18 10 20 10 15 27 23 12 12 0 12 21 24 25 12 + 12 12 23 12 12 23 12 12 12 10 12 24 12 12 26 23 12 + 20 25 18 14 30 11 19 12 12 12 14 10 31 15 25 27 10 + 12 12 21 24 12 12 24 15 12 14 12 30 12 28 12 12 12 + 12 12 12 12 12 23 12 10 23 12 12 12 23 14 12 24 16 + 12 11 23 18 23 18 23 25 12 12 12 12 12 12 12 12 18 + 12 12 27 12 12 12 12 23 27 12 12 27 16 11 16 30 23 + 28 25 25 24 21 26 26 11 18 11 11 10 15 23 11 11 23 + 24 24 23 30 31 25 25 25 10 28 29 25 25 25 23 27 30 + 23 28 25 11 12 30 25 30 15 23 10 19 24 12 27 12 30 + 23 15 19 24 30 23 23 19 10 25 24 25 23 30 11 26 23 + 23 23 24 30 30 10 16 20 28 23 27 23 25 28 11 20 19 + 24 23 0 16 10 26 18 30 16 19 25 12 25 24 26 25 20 + 19 25 24 25 0 23 25 31 15 31 19 24 19 23 29 23 12 + 29 30 26 20 21 14 10 24 24 27 11 12 24 30 11 20 15 + 27 10 11 10 15 27 15 27 11 26 14 10 19 24 10 15 26 + 11 25 24 30 21 23 12 23 11 15 12 24 25 6 26 25 12 + 30 19 15 0 29 12 0 0 11 27 21 19 11 18 15 31 26 + + 24 24 24 14 31 14 15 24 24 23 12 16 23 23 26 15 28 + 15 20 20 15 21 11 10 28 24 14 14 15 14 23 25 25 14 + 14 14 24 14 14 24 14 14 14 15 14 24 15 14 27 24 12 + 21 25 20 15 31 15 12 12 14 14 15 15 31 10 25 28 9 + 14 14 23 24 14 14 24 16 14 15 14 31 14 28 14 14 14 + 14 14 14 14 14 24 14 15 24 14 14 14 23 15 14 24 18 + 14 15 23 20 23 20 23 25 14 14 14 14 14 14 14 14 20 + 14 14 27 14 14 14 14 24 27 14 14 27 18 15 18 31 24 + 28 26 25 25 23 27 27 15 20 15 15 15 12 24 15 10 24 + 24 24 24 31 31 25 26 26 15 29 30 26 26 26 24 27 31 + 24 29 26 15 14 31 26 31 11 23 10 4 25 15 27 12 31 + 23 10 11 25 31 24 23 11 15 25 24 26 23 31 15 27 24 + 24 24 24 31 31 15 18 21 29 24 28 23 25 28 15 21 16 + 24 24 15 18 15 27 20 31 18 10 25 14 26 24 27 25 21 + 11 25 25 25 15 24 26 31 10 31 4 24 20 23 30 24 14 + 30 31 27 21 23 15 15 24 24 27 15 12 24 31 12 21 11 + 28 4 10 15 12 27 12 28 15 27 15 15 18 24 15 10 27 + 12 25 25 31 23 24 12 24 15 12 14 24 25 10 27 25 15 + 31 10 0 15 30 14 15 14 0 28 23 10 15 20 16 31 27 + + 24 24 24 10 31 10 16 24 24 23 14 18 23 23 27 15 28 + 0 21 21 10 23 12 15 28 24 10 10 11 10 23 25 26 10 + 10 10 24 10 10 24 10 10 10 10 10 25 14 10 27 24 14 + 23 26 21 16 31 0 19 14 10 10 16 10 31 15 26 28 10 + 10 10 23 24 10 10 24 18 10 16 10 31 10 29 10 10 10 + 10 10 10 10 10 24 10 10 24 10 10 10 24 16 10 24 20 + 15 0 24 21 24 21 23 26 10 10 10 10 10 10 10 10 21 + 10 10 28 10 10 10 10 24 28 15 15 28 20 0 20 31 24 + 29 27 26 25 23 27 27 0 21 12 0 10 15 24 0 6 24 + 24 24 24 31 31 26 27 27 10 30 31 27 27 27 24 28 31 + 24 30 27 0 15 31 27 31 15 23 11 19 25 15 28 14 31 + 23 15 19 25 31 24 24 19 10 26 24 27 24 31 0 27 24 + 24 24 25 31 31 10 20 23 30 24 28 23 26 29 0 23 19 + 25 24 11 20 12 27 21 31 20 19 26 15 27 25 27 26 23 + 19 26 25 26 11 24 27 31 15 31 19 25 21 24 31 24 15 + 31 31 27 23 23 16 10 24 24 28 0 14 24 31 12 23 15 + 28 10 6 10 15 28 15 28 0 27 16 12 20 24 10 15 27 + 12 26 25 31 23 24 14 24 0 15 15 24 26 11 27 26 14 + 31 19 15 11 31 15 11 15 0 0 23 19 0 21 18 31 27 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 0 18 10 23 20 33 28 + + 17 12 12 23 24 23 14 12 24 5 16 12 6 6 18 15 23 + 23 11 11 23 10 20 23 23 19 23 23 21 23 10 15 16 23 + 23 23 21 23 23 23 23 23 23 23 23 14 16 23 20 23 16 + 10 16 11 14 24 23 19 16 23 23 14 23 24 23 16 23 23 + 23 23 15 12 23 23 24 12 23 14 23 24 23 23 23 23 23 + 23 23 23 23 23 12 23 23 12 23 23 23 11 14 23 12 12 + 15 23 11 11 11 11 10 16 23 23 23 23 23 23 23 23 11 + 23 23 21 23 23 23 23 12 21 15 15 21 12 23 12 24 12 + 23 18 16 15 10 20 20 23 14 18 23 23 18 16 23 23 12 + 12 12 17 24 24 16 18 18 23 23 24 18 18 18 22 21 24 + 12 23 18 23 15 24 18 24 20 19 21 23 15 15 21 16 24 + 10 21 20 15 24 12 15 23 23 16 12 18 11 24 23 20 12 + 23 12 14 24 24 23 12 10 23 12 23 10 16 23 23 10 19 + 14 19 21 12 20 20 11 24 14 21 16 15 18 14 20 16 15 + 23 16 15 16 21 17 18 24 21 24 23 14 19 11 24 15 15 + 24 24 20 10 5 14 23 12 12 21 23 16 12 24 18 19 20 + 23 23 23 23 18 21 16 23 23 20 14 20 19 12 23 23 20 + 18 16 19 24 14 12 16 12 23 18 15 12 16 21 20 16 16 + 24 21 23 21 24 15 21 15 23 23 0 0 23 11 12 24 20 + + 23 23 23 14 28 14 12 23 23 18 10 15 18 18 24 15 26 + 15 15 15 15 16 10 12 26 23 14 14 15 14 18 24 24 14 + 14 14 23 14 14 23 14 14 14 15 14 23 15 14 25 23 10 + 16 24 15 12 28 15 4 10 14 14 12 15 29 12 24 26 12 + 14 14 18 23 14 14 23 12 14 12 14 28 14 27 14 14 14 + 14 14 14 14 14 23 14 15 23 14 14 14 21 12 14 23 14 + 11 15 21 15 21 15 20 24 14 14 14 14 14 14 14 14 15 + 14 14 25 14 14 14 14 23 25 11 11 25 14 15 14 28 23 + 27 24 24 24 18 25 25 15 15 15 15 15 0 23 15 12 23 + 23 23 23 28 29 24 24 24 15 27 28 24 24 24 23 25 28 + 23 27 24 15 11 28 24 28 10 20 11 12 24 15 25 10 28 + 20 11 10 24 28 23 21 14 15 24 23 24 21 28 15 25 23 + 23 23 23 28 28 15 14 16 27 23 26 20 24 27 15 16 12 + 23 23 15 14 15 25 15 28 14 11 24 11 24 23 25 24 16 + 14 24 24 24 15 23 24 29 11 29 12 23 15 21 28 23 11 + 28 28 25 16 18 12 15 23 23 25 15 10 23 28 4 16 10 + 26 12 12 15 0 25 10 26 15 25 12 15 14 23 15 12 25 + 9 24 24 28 18 23 10 23 15 0 11 23 24 11 25 24 15 + 28 11 12 15 28 11 15 11 15 26 18 11 0 15 15 29 25 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 0 20 33 28 + + 24 24 25 0 31 0 18 25 24 23 15 20 23 23 27 16 29 + 10 23 23 11 23 12 14 29 24 0 0 12 0 23 26 27 0 + 0 0 24 0 0 24 0 0 0 11 0 25 15 0 28 24 15 + 23 27 23 18 31 10 18 15 0 0 18 11 33 14 27 29 11 + 0 0 23 25 0 0 24 20 0 18 0 31 0 30 0 0 0 + 0 0 0 0 0 24 0 11 24 0 0 0 24 18 0 25 21 + 16 10 24 23 24 23 24 27 0 0 0 0 0 0 0 0 23 + 0 0 28 0 0 0 0 24 28 16 16 28 21 10 21 31 24 + 30 27 27 26 23 28 28 10 23 14 10 11 14 24 10 10 24 + 25 25 24 31 33 27 27 27 11 31 31 27 27 27 24 28 31 + 24 31 27 10 16 31 27 31 14 24 12 18 26 16 28 15 31 + 24 14 18 26 31 24 24 18 11 27 25 27 24 31 10 28 24 + 24 24 25 31 31 11 21 23 31 24 29 24 27 30 10 23 20 + 25 24 12 21 12 28 23 31 21 18 27 16 27 25 28 27 23 + 18 27 26 27 12 24 27 33 14 33 18 25 23 24 31 24 16 + 31 31 28 23 23 18 11 25 25 28 10 15 25 31 14 23 14 + 29 11 10 11 14 28 15 29 10 28 18 12 21 25 11 14 28 + 14 27 26 31 23 24 15 24 10 14 16 25 27 12 28 27 15 + 31 18 14 12 31 16 12 16 10 29 23 18 10 23 0 33 28 + + 17 14 15 23 25 23 12 15 24 11 14 11 11 11 21 12 23 + 21 6 11 20 10 16 21 23 19 23 23 18 23 11 18 20 23 + 23 23 21 23 23 23 23 23 23 20 23 16 14 23 23 23 14 + 10 20 8 12 25 21 19 14 23 23 12 20 25 21 20 23 20 + 23 23 15 15 23 23 24 11 23 12 23 25 23 24 23 23 23 + 23 23 23 23 23 14 23 20 14 23 23 23 12 12 23 15 10 + 12 21 12 8 12 5 12 20 23 23 23 23 23 23 23 23 11 + 23 23 23 23 23 23 23 14 23 12 12 23 10 21 10 25 14 + 24 21 20 18 11 23 23 21 14 15 21 20 15 16 21 21 14 + 15 15 17 25 25 20 21 21 20 24 24 21 21 21 22 23 25 + 14 24 21 21 12 25 21 25 16 19 18 20 18 12 23 14 25 + 12 18 19 18 25 14 15 23 20 20 15 21 12 25 21 23 14 + 23 14 16 25 25 20 10 10 24 14 23 12 20 24 21 10 19 + 16 19 18 10 16 23 11 25 14 19 20 12 21 16 23 20 15 + 23 20 18 20 18 17 21 25 18 25 20 16 19 12 24 15 12 + 24 25 23 10 11 12 20 15 15 23 21 14 15 25 15 19 16 + 23 20 21 20 15 23 15 23 21 23 12 16 19 15 20 21 23 + 15 20 19 25 14 14 14 14 21 15 12 15 20 18 23 20 14 + 25 19 20 18 24 12 18 12 21 23 11 19 21 0 11 0 23 + + 17 16 18 20 26 20 10 18 24 12 12 0 12 12 23 11 24 + 18 11 11 16 12 14 18 24 19 20 20 15 20 12 21 23 20 + 20 20 21 20 20 23 20 20 20 16 20 20 12 20 23 23 12 + 12 23 11 10 26 18 19 12 20 20 10 16 27 18 23 24 16 + 20 20 15 18 20 20 24 8 20 11 20 26 20 24 20 20 20 + 20 20 20 20 20 16 20 16 16 20 20 20 15 10 20 18 10 + 11 18 15 11 15 11 14 23 20 20 20 20 20 20 20 20 11 + 20 20 24 20 20 20 20 16 24 11 11 24 10 18 10 26 16 + 24 23 23 21 12 23 23 18 14 12 18 16 15 16 18 18 16 + 18 18 17 26 27 23 23 23 16 25 25 23 23 23 22 24 26 + 16 25 23 18 12 26 23 26 15 19 15 19 21 11 24 12 26 + 14 15 19 21 26 16 15 20 16 23 18 23 15 26 18 23 16 + 23 16 20 26 26 16 10 12 25 16 24 14 23 24 18 12 19 + 20 19 15 10 14 23 11 26 14 19 23 11 23 20 23 23 15 + 20 23 21 23 15 17 23 27 15 27 19 20 19 15 25 16 11 + 25 26 23 12 12 10 16 18 18 24 18 12 18 26 12 19 15 + 24 16 18 16 15 24 15 24 18 23 10 14 19 18 16 18 23 + 12 23 21 26 14 16 12 16 18 15 11 18 23 15 23 23 12 + 26 19 16 15 25 11 15 11 18 24 12 19 18 11 0 27 0 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ry48p.atsp b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ry48p.atsp new file mode 100644 index 0000000..b02a98c --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ATSP-instances/ry48p.atsp @@ -0,0 +1,200 @@ +NAME: ry48p +TYPE: ATSP +COMMENT: Asymmetric TSP (Fischetti) +DIMENSION: 48 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: FULL_MATRIX +EDGE_WEIGHT_SECTION + 9999999 1593 569 2056 1327 1009 947 301 234 1800 625 700 754 790 529 + 395 1385 856 1179 821 1085 385 730 1808 915 2076 1120 1002 1297 1026 + 592 1448 694 743 2254 880 1137 330 1121 449 786 1594 1264 755 2354 + 593 849 1216 + 1619 9999999 1191 656 595 2304 2128 1797 1674 834 1348 1620 1183 1050 1629 + 1339 2444 2039 2350 1646 1334 1322 1167 1079 1182 624 2307 2171 478 2272 + 1923 1192 1837 982 1060 2132 2312 1884 1047 1513 1051 550 2287 2125 1123 + 1765 1388 718 + 528 1297 9999999 1682 809 1309 1170 624 506 1445 526 488 561 402 610 + 429 1510 1072 1419 882 801 250 401 1351 485 1579 1436 1194 898 1194 + 816 1054 728 471 1828 1000 1276 837 898 465 459 1183 1314 989 1876 + 708 620 968 + 2097 723 1781 9999999 996 2674 2595 2360 2236 501 1846 2061 1616 1580 2108 + 1884 2678 2590 2635 2068 1584 1847 1638 930 1328 187 2635 2582 948 2669 + 2421 1197 2183 1506 620 2438 2782 2337 1328 1959 1513 680 2603 2497 648 + 2142 1827 1058 + 1310 680 780 1023 9999999 1690 1754 1424 1279 787 900 1153 759 612 1201 + 1098 1918 1682 1858 1148 876 975 761 759 639 820 1759 1651 417 1694 + 1459 718 1292 566 1005 1632 1870 1540 493 1131 954 496 1760 1629 1144 + 1306 886 295 + 1156 2218 1336 2687 1745 9999999 358 1020 964 2253 998 774 1089 1369 692 + 1349 364 339 249 801 1187 1286 1135 2157 1442 2473 276 303 1881 258 + 681 1588 708 1488 2624 391 254 704 1508 879 1636 2165 300 429 2588 + 668 1014 1735 + 827 2103 1085 2504 1692 258 9999999 972 759 2236 834 724 970 1102 604 + 1227 535 54 493 551 1165 1066 974 1908 1239 2379 508 124 1677 311 + 386 1483 590 1382 2444 204 391 614 1437 820 1410 2049 471 245 2595 + 386 858 1615 + 190 1684 698 2274 1395 1116 792 9999999 387 2016 797 691 984 1055 677 + 445 1348 868 1148 936 1246 404 816 1965 1191 2206 1272 1050 1323 1057 + 505 1607 839 890 2379 972 1098 327 1471 545 973 1756 1200 786 2415 + 616 920 1552 + 217 1673 526 2144 1366 1009 796 413 9999999 1941 696 570 899 793 452 + 515 1094 619 1003 758 937 524 615 1760 1020 2103 1133 749 1323 900 + 465 1379 477 762 2222 632 1020 317 1178 247 908 1609 1140 473 2205 + 392 824 1237 + 1892 856 1591 636 780 2323 2205 2133 2014 9999999 1544 1649 1258 1170 1709 + 1716 2377 2141 2443 1629 1320 1686 1395 378 1015 383 2367 2191 833 2283 + 2062 800 1897 1257 448 2138 2287 2109 803 1810 1520 415 2270 2119 478 + 1932 1486 706 + 660 1316 535 1817 893 1084 780 764 592 1407 9999999 323 304 464 344 + 787 1129 839 1180 507 450 669 189 1400 416 1760 992 905 963 975 + 745 890 503 643 1901 829 1118 775 749 403 986 1343 1039 813 1921 + 564 418 853 + 673 1626 580 1892 1168 829 719 745 438 1582 366 9999999 537 648 217 + 787 1031 541 896 370 568 609 434 1536 589 1928 807 792 1282 790 + 677 930 214 705 1993 690 926 561 936 442 987 1422 772 547 1895 + 410 343 1015 + 786 1289 570 1603 682 1203 1059 956 885 1353 297 547 9999999 328 632 + 937 1377 1023 1316 495 332 849 227 1130 254 1474 1322 1106 933 1097 + 955 530 617 535 1634 949 1254 884 521 702 891 1051 1127 1096 1568 + 844 326 758 + 776 1066 499 1584 536 1245 1106 1016 913 1157 331 690 236 9999999 746 + 720 1414 1137 1420 747 457 711 234 1016 211 1370 1479 1144 617 1341 + 1115 761 697 443 1549 1172 1452 939 461 555 768 949 1319 1135 1589 + 791 555 566 + 434 1750 629 2111 1152 812 635 592 499 1693 299 220 686 769 9999999 + 837 1005 609 839 473 664 664 440 1510 773 2009 952 567 1243 788 + 531 1137 228 918 2134 466 902 500 1012 333 916 1638 889 435 2012 + 373 519 1160 + 430 1369 449 1956 1178 1364 1169 534 490 1736 747 829 850 721 832 + 9999999 1524 1019 1405 1055 1018 221 649 1586 854 1849 1420 1180 1082 1460 + 920 1405 886 659 2137 1144 1366 685 1164 621 512 1489 1507 1040 2047 + 848 988 1247 + 1295 2527 1426 2755 1976 340 497 1247 1189 2385 1187 918 1228 1425 1065 + 1531 9999999 659 233 866 1323 1565 1347 2089 1544 2637 126 545 2079 346 + 772 1567 751 1683 2693 613 274 1026 1535 1207 1826 2313 171 795 2715 + 822 1033 1946 + 851 2101 1064 2399 1615 452 196 834 668 2196 775 586 1078 1175 512 + 1028 645 9999999 513 509 1136 909 1009 1929 1194 2379 419 165 1787 323 + 377 1412 467 1184 2407 118 370 608 1422 609 1362 2042 507 269 2516 + 311 838 1685 + 1210 2372 1385 2679 1919 125 516 1170 1001 2442 1102 873 1280 1418 955 + 1398 269 524 9999999 759 1146 1399 1311 2170 1428 2617 79 287 2039 310 + 680 1564 664 1553 2738 407 99 894 1569 1003 1787 2101 329 655 2629 + 808 934 1871 + 723 1779 819 2056 1170 726 592 967 815 1664 406 377 543 649 370 + 1104 750 631 866 9999999 499 841 652 1371 782 1895 694 658 1243 682 + 724 937 213 1047 2019 544 735 791 814 500 1189 1511 799 550 1948 + 438 262 1047 + 1005 1475 840 1600 715 1188 1122 1256 970 1208 508 618 304 615 716 + 999 1175 1107 1206 542 9999999 984 461 1106 460 1480 1125 1128 1115 1054 + 1132 571 755 708 1546 1033 1198 987 545 798 1228 1161 1075 1037 1506 + 876 346 791 + 404 1421 317 1918 1059 1275 1025 420 534 1663 616 660 745 742 683 + 328 1491 904 1452 882 921 9999999 559 1624 718 1903 1280 1053 978 1282 + 710 1140 809 557 2124 984 1278 702 1022 491 558 1414 1335 949 2111 + 695 791 1189 + 546 1189 345 1638 718 1246 1034 781 682 1314 251 504 225 264 593 + 685 1412 863 1312 570 521 614 9999999 1221 414 1559 1246 970 860 1134 + 868 724 662 436 1807 986 1162 706 620 469 665 1181 1090 930 1741 + 586 412 770 + 1695 962 1414 866 621 1982 1923 1990 1749 352 1256 1480 1015 1106 1502 + 1646 2199 1954 2105 1419 1063 1542 1227 9999999 875 798 2153 1991 950 1929 + 1892 683 1620 1115 725 1886 2083 1857 766 1520 1554 459 2052 2040 646 + 1834 1330 537 + 952 1029 537 1441 451 1411 1250 1051 833 1110 524 581 184 228 691 + 923 1568 1237 1419 765 423 873 429 1023 9999999 1310 1350 1283 719 1235 + 1158 538 901 518 1452 1060 1373 1166 461 645 851 966 1332 1218 1365 + 945 553 568 + 2061 722 1713 298 813 2633 2414 2254 2162 487 1606 1867 1419 1350 1900 + 1728 2730 2455 2548 1965 1542 1732 1654 755 1299 9999999 2571 2564 831 2422 + 2357 1210 2057 1254 464 2359 2669 2163 1071 1856 1577 497 2540 2371 714 + 2232 1643 952 + 1173 2364 1322 2759 1912 246 530 1243 1011 2335 1125 907 1166 1454 860 + 1547 298 463 75 661 1197 1362 1227 2108 1302 2550 9999999 381 2018 248 + 661 1602 780 1547 2606 420 191 880 1573 1000 1781 2079 174 619 2648 + 753 963 1735 + 872 2158 1106 2574 1739 273 278 943 833 2234 799 677 1120 1245 559 + 1161 484 163 337 574 1169 1163 970 2001 1196 2375 300 9999999 1849 265 + 508 1383 470 1421 2587 298 224 586 1380 880 1471 2064 358 421 2425 + 553 898 1601 + 1284 503 875 979 375 1874 1736 1429 1243 911 1052 1170 836 658 1334 + 1037 1998 1731 2002 1427 1041 1120 857 969 674 971 1966 1800 9999999 1785 + 1630 936 1323 562 1243 1670 2000 1464 791 1188 747 482 2009 1704 1232 + 1380 1060 565 + 1099 2354 1305 2528 1734 138 418 1078 934 2189 1030 752 1046 1218 717 + 1360 411 417 261 556 1122 1145 1085 1986 1225 2534 255 247 1956 9999999 + 596 1445 581 1540 2501 244 146 896 1491 946 1677 2102 263 483 2439 + 674 965 1749 + 672 1921 948 2388 1537 594 394 495 425 2053 849 589 973 1137 388 + 847 886 350 613 693 1076 778 791 1943 1066 2367 690 390 1561 612 + 9999999 1467 530 1124 2558 369 690 287 1441 455 1363 1989 709 283 2489 + 373 800 1504 + 1387 1277 1020 1219 545 1467 1455 1553 1281 883 765 950 675 770 1139 + 1245 1543 1437 1541 853 570 1325 824 534 657 1287 1625 1490 863 1468 + 1542 9999999 1015 891 1183 1448 1554 1406 266 1142 1162 765 1435 1465 1175 + 1278 700 632 + 747 1668 719 2159 1183 633 500 722 525 1896 400 251 636 742 322 + 812 931 385 692 236 727 855 678 1643 847 1988 774 490 1324 685 + 411 1093 9999999 1028 2141 469 655 532 1049 427 1228 1649 725 424 2064 + 190 462 1251 + 702 1023 383 1383 644 1420 1272 914 824 1280 575 723 604 352 820 + 695 1665 1366 1642 867 806 648 542 1173 567 1316 1504 1408 601 1556 + 1093 826 937 9999999 1521 1187 1466 964 764 617 399 1000 1492 1147 1647 + 980 701 554 + 2318 1080 1876 516 1131 2587 2633 2328 2298 516 1836 2047 1595 1561 2094 + 2137 2690 2509 2644 1942 1545 1967 1716 700 1385 594 2612 2552 1137 2467 + 2474 1260 2162 1513 9999999 2468 2699 2387 1201 2007 1886 661 2545 2527 285 + 2358 1796 954 + 789 2177 966 2481 1629 411 179 930 754 2061 841 687 957 1116 621 + 1236 636 263 374 506 985 1055 927 1804 1104 2429 390 232 1693 296 + 499 1359 448 1361 2370 9999999 353 488 1394 800 1428 1896 532 217 2479 + 423 825 1536 + 1154 2403 1241 2712 1817 176 340 1199 1014 2320 1146 874 1232 1392 791 + 1398 350 419 151 739 1116 1282 1204 2209 1436 2570 289 240 1959 237 + 591 1666 726 1490 2732 312 9999999 855 1610 1063 1665 2126 207 600 2664 + 754 1054 1852 + 514 1895 655 2265 1531 739 492 329 290 2007 671 615 962 939 389 + 708 1052 549 850 682 1173 592 708 1878 1139 2305 1015 636 1528 843 + 313 1391 469 1078 2343 529 887 9999999 1286 361 1114 1923 979 340 2437 + 474 928 1576 + 1232 1141 943 1222 534 1485 1372 1439 1153 879 678 862 390 611 949 + 1157 1610 1385 1532 829 382 1057 770 734 483 1183 1580 1504 754 1350 + 1357 255 1001 641 1214 1312 1653 1420 9999999 1030 1168 709 1451 1329 1247 + 1090 653 364 + 262 1623 397 1915 1050 898 682 573 237 1775 342 439 636 698 196 + 638 1092 683 1125 578 695 364 487 1644 667 1815 1011 842 1238 1022 + 543 1179 456 771 2058 795 910 449 1058 9999999 812 1411 1112 610 2066 + 417 574 1033 + 798 1070 476 1489 790 1729 1582 940 954 1562 957 922 957 695 1068 + 567 1847 1458 1743 1210 1096 627 846 1502 838 1554 1835 1462 709 1766 + 1195 1150 1063 496 1727 1452 1803 1194 997 833 9999999 1159 1857 1385 1819 + 1098 1074 907 + 1536 598 1201 631 449 2195 2058 1776 1767 494 1261 1519 1138 900 1547 + 1459 2231 1924 2156 1470 993 1388 1175 407 955 569 2225 2090 501 2123 + 2002 841 1592 988 699 1868 2137 1899 658 1530 1127 9999999 2060 1916 745 + 1667 1272 510 + 1176 2389 1379 2717 1694 332 408 1260 1022 2321 1004 879 1079 1384 814 + 1588 250 496 217 685 1100 1308 1175 1985 1293 2589 236 498 1912 170 + 709 1428 781 1574 2471 530 212 851 1544 1096 1675 2133 9999999 708 2454 + 706 907 1672 + 619 2085 990 2459 1541 520 280 793 507 2204 821 644 1092 1176 420 + 948 636 231 605 629 1046 945 831 1990 1162 2387 600 416 1766 494 + 197 1483 420 1173 2410 250 615 445 1441 539 1294 1902 590 9999999 2434 + 423 757 1531 + 2281 1127 1889 727 1131 2498 2445 2443 2350 594 1874 2030 1591 1659 2192 + 2056 2593 2501 2532 1979 1553 2056 1761 577 1529 595 2553 2613 1292 2555 + 2474 1123 2106 1632 324 2448 2712 2465 1183 2151 1793 795 2542 2526 9999999 + 2196 1783 1001 + 584 1919 727 2331 1424 610 491 761 514 1839 455 427 733 833 282 + 933 769 376 712 433 886 636 694 1782 964 2210 748 583 1400 675 + 375 1234 152 1078 2279 377 665 332 1160 485 1090 1641 631 415 2342 + 9999999 645 1281 + 856 1456 670 1757 900 860 842 1110 831 1365 324 480 335 625 525 + 981 1008 896 1082 250 274 802 470 1140 486 1609 1062 832 1051 937 + 914 615 426 857 1856 786 1087 955 560 646 1048 1351 1035 809 1752 + 679 9999999 811 + 1209 724 957 1012 248 1750 1558 1373 1393 683 957 1018 588 633 1190 + 1169 1840 1656 1912 1112 811 1188 873 590 428 984 1759 1682 509 1743 + 1590 480 1202 703 1134 1594 1913 1515 346 1227 968 537 1714 1616 1145 + 1371 902 9999999 +EOF diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/pbm.txt b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/pbm.txt new file mode 100644 index 0000000..38c5037 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/pbm.txt @@ -0,0 +1,2 @@ +30 +/Mallba/ProblemInstances/DNAFA-instances/x60189_4.dat diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/score.txt b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/score.txt new file mode 100644 index 0000000..ff26d92 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/score.txt @@ -0,0 +1,39 @@ + 0 1 0 304 1 1 1 0 7 -163 247 1 2 1 1 0 0 2 0 1 1 1 2 1 1 107 0 1 3 1 1 0 1 286 1 3 0 1 1 + 1 0 1 1 -3 3 -1 331 -302 2 5 0 1 0 0 -1 -2 -2 2 281 0 -413 1 0 168 -2 2 0 -3 39 412 2 155 1 4 247 274 0 53 + 0 1 0 -2 225 0 2 1 0 -1 1 178 1 2 -2 -1 -2 -149 -3 -1 -2 2 1 366 -2 4 2 -2 -7 -2 -3 -363 -2 -2 -327 -1 -1 -353 -3 + 304 1 -2 0 -1 -27 -1 0 -1 -160 327 -3 43 -1 1 4 1 2 1 -1 1 -4 2 1 1 200 -1 1 1 1 1 2 1 283 -1 3 3 1 1 + 1 -3 225 -1 0 -2 -3 -3 -2 -1 0 1 0 -1 1 -1 -1 -279 -2 -2 2 0 -106 104 -2 1 2 -2 2 -1 -1 -252 0 -1 -65 0 -1 -250 -1 + 1 3 0 -27 -2 0 1 0 -2 -1 -14 -1 -346 1 -1 6 -88 -1 -241 -2 -1 1 0 1 -2 -276 1 -2 2 -2 -2 1 1 -1 -3 -1 0 3 3 + 1 -1 2 -1 -3 1 0 0 1 -1 -3 -1 2 -6 -414 0 -1 -2 -1 1 -301 2 99 1 1 1 271 6 1 -1 -1 -2 1 -1 1 -3 -2 -1 -1 + 0 331 1 0 -3 0 0 0 -302 0 1 0 1 0 0 1 2 2 3 185 0 -317 1 0 72 -4 2 0 0 2 316 2 155 0 0 247 178 0 3 + 7 -302 0 -1 -2 -2 1 -302 0 -26 2 -1 2 -4 -1 0 -1 -2 -1 -156 -1 288 -2 1 -43 1 1 -2 3 -1 -287 1 -306 -1 1 -377 -149 -1 -1 + -163 2 -1 -160 -1 -1 -1 0 -26 0 -103 2 1 -1 2 1 0 -1 0 -2 1 -1 -1 1 1 0 0 1 1 2 2 1 76 -289 -2 5 -2 2 2 + 247 5 1 327 0 -14 -3 1 2 -103 0 1 30 1 1 1 1 0 -2 1 2 0 1 0 -4 187 2 0 0 0 0 0 0 226 1 0 1 2 5 + 1 0 178 -3 1 -1 -1 0 -1 2 1 0 1 0 -2 -1 1 1 1 2 0 1 2 271 0 1 -1 -4 -309 161 1 -54 0 1 -316 -1 2 -44 23 + 2 1 1 43 0 -346 2 1 2 1 30 1 0 1 1 1 150 0 303 1 1 0 1 0 0 292 1 0 0 0 0 0 0 -2 1 0 1 1 0 + 1 0 2 -1 -1 1 -6 0 -4 -1 1 0 1 0 6 260 -251 2 -123 0 6 2 -1 0 0 1 -2 -300 0 2 -1 -2 0 -1 0 -3 -2 0 -1 + 1 0 -2 1 1 -1 -414 0 -1 2 1 -2 1 6 0 -1 1 1 3 2 301 -2 -79 0 0 1 -251 -6 0 1 1 2 0 1 2 3 2 0 1 + 0 -1 -1 4 -1 6 0 1 0 1 1 -1 1 260 -1 0 -306 2 -178 1 -2 -1 -1 0 0 -4 -2 -100 0 2 3 -2 0 0 1 1 1 -3 3 + 0 -2 -2 1 -1 -88 -1 2 -1 0 1 1 150 -251 1 -306 0 2 339 -1 1 -1 -1 1 1 18 -2 91 1 2 3 -2 1 1 -1 1 1 1 3 + 2 -2 -149 2 -279 -1 -2 2 -2 -1 0 1 0 2 1 2 2 0 -1 -1 1 -1 252 -28 1 2 115 3 1 1 1 176 1 2 -1 1 -1 174 1 + 0 2 -3 1 -2 -241 -1 3 -1 0 -2 1 303 -123 3 -178 339 -1 0 -1 1 -1 -1 1 1 171 0 1 1 2 2 1 1 1 -2 2 1 2 2 + 1 281 -1 -1 -2 -2 1 185 -156 -2 1 2 1 0 2 1 -1 -1 -1 0 0 -312 -1 0 324 1 1 -2 2 214 313 1 9 -1 -3 101 310 3 228 + 1 0 -2 1 2 -1 -301 0 -1 1 2 0 1 6 301 -2 1 1 1 0 0 -2 1 0 0 1 -138 -6 0 1 1 3 0 1 0 3 2 0 1 + 1 -413 2 -4 0 1 2 -317 288 -1 0 1 0 2 -2 -1 -1 -1 -1 -312 -2 0 1 -2 -199 1 1 -2 0 -70 -443 -2 -141 -2 3 -233 -305 1 -84 + 2 1 1 2 -106 0 99 1 -2 -1 1 2 1 -1 -79 -1 -1 252 -1 -1 1 1 0 -2 0 2 228 0 -2 0 0 3 -2 2 -1 2 -1 1 0 + 1 0 366 1 104 1 1 0 1 1 0 271 0 0 0 0 1 -28 1 0 0 -2 -2 0 0 1 -3 0 -100 1 1 -242 0 3 -420 0 2 -232 1 + 1 168 -2 1 -2 -2 1 72 -43 1 -4 0 0 0 0 0 1 1 1 324 0 -199 0 0 0 1 -3 -2 2 195 200 2 0 1 -3 0 204 3 209 + 107 -2 4 200 1 -276 1 -4 1 0 187 1 292 1 1 -4 18 2 171 1 1 1 2 1 1 0 0 1 -3 -2 -2 0 1 86 2 3 0 -2 -2 + 0 2 2 -1 2 1 271 2 1 0 2 -1 1 -2 -251 -2 -2 115 0 1 -138 1 228 -3 -3 0 0 1 1 -1 -1 -1 -3 -1 1 -2 -1 -1 -1 + 1 0 -2 1 -2 -2 6 0 -2 1 0 -4 0 -300 -6 -100 91 3 1 -2 -6 -2 0 0 -2 1 1 0 2 1 1 2 0 1 0 3 2 0 1 + 3 -3 -7 1 2 2 1 0 3 1 0 -309 0 0 0 0 1 1 1 2 0 0 -2 -100 2 -3 1 2 0 -141 1 1 0 -3 145 0 0 -3 -3 + 1 39 -2 1 -1 -2 -1 2 -1 2 0 161 0 2 1 2 2 1 2 214 1 -70 0 1 195 -2 -1 1 -141 0 71 -1 1 1 -1 1 75 1 291 + 1 412 -3 1 -1 -2 -1 316 -287 2 0 1 0 -1 1 3 3 1 2 313 1 -443 0 1 200 -2 -1 1 1 71 0 -1 140 1 -2 232 306 2 85 + 0 2 -363 2 -252 1 -2 2 1 1 0 -54 0 -2 2 -2 -2 176 1 1 3 -2 3 -242 2 0 -1 2 1 -1 -1 0 2 2 203 -1 1 378 -1 + 1 155 -2 1 0 1 1 155 -306 76 0 0 0 0 0 0 1 1 1 9 0 -141 -2 0 0 1 -3 0 0 1 140 2 0 3 0 285 2 0 1 + 286 1 -2 283 -1 -1 -1 0 -1 -289 226 1 -2 -1 1 0 1 2 1 -1 1 -2 2 3 1 86 -1 1 -3 1 1 2 3 0 -1 3 2 1 1 + 1 4 -327 -1 -65 -3 1 0 1 -2 1 -316 1 0 2 1 -1 -1 -2 -3 0 3 -1 -420 -3 2 1 0 145 -1 -2 203 0 -1 0 1 -2 193 4 + 3 247 -1 3 0 -1 -3 247 -377 5 0 -1 0 -3 3 1 1 1 2 101 3 -233 2 0 0 3 -2 3 0 1 232 -1 285 3 1 0 94 -2 1 + 0 274 -1 3 -1 0 -2 178 -149 -2 1 2 1 -2 2 1 1 -1 1 310 2 -305 -1 2 204 0 -1 2 0 75 306 1 2 2 -2 94 0 -1 89 + 1 0 -353 1 -250 3 -1 0 -1 2 2 -44 1 0 0 -3 1 174 2 3 0 1 1 -232 3 -2 -1 0 -3 1 2 378 0 1 193 -2 -1 0 2 + 1 53 -3 1 -1 3 -1 3 -1 2 5 23 0 -1 1 3 3 1 2 228 1 -84 0 1 209 -2 -1 1 -3 291 85 -1 1 1 4 1 89 2 0 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/x60189_4.dat b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/x60189_4.dat new file mode 100644 index 0000000..2420540 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/DNAFA-instances/x60189_4.dat @@ -0,0 +1,78 @@ +>frag0000 +caccatctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtg +>frag0001 +agcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcc +>frag0002 +agggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaacacgcaccgcctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcaaagcggccctgggggacggtccaggaaaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctcgtccacatcctcttgtggggctgaaaggtaatatagggggatacagagtttaagggtttaagggcaacttgctttgctggtgctgtcaacagaggtcatacatcaaatgcgcccctccaga +>frag0003 +catctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaagaatgggcttttc +>frag0004 +gctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctcgtccacatcctcttgtggggctgaaaggtaatatagggggatacagagtttaagggtttaagggcaacttgctttgctggtgctgtcaacagaggtcatacatcaaatgcgcccctccagagcaggctgagggctggggcagctttgagttcgccgttcagtgactcttggaataagagccggtgaggtatccccgagcccccgactgtactgctggcagagctgcactgttagaaacctccagaaggcaa +>frag0005 +gcccctgacacgcatcacctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcgaagtggccctgggggatggtccaggagaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagcggctcctcagggggctccggggcctcagtgctgagttccgtggggctgggggtctcttcctctgcagctgagaaaaggagatatagagaggatgccaggtgcctgggggatgtgctcaggtcttcaagggaaggagggagaaaccatggccactactgggtatgtgaggtcatttcagaaaagcccattcttggggctgggtgg +>frag0006 +gaattcccaacctcaggtgatccacccgcctcggcctcccaaaatgctaggattacaggcgtgaaccactgctcccagcccagaatttcttttttagcccacgtttttctagtgaaaataatacagcaacattatgtggaaagcttgaaaaacagaaaacaagaatctcatagtcctactttctcccccagctgccggcattaataacaatgtgtgtagtgcacattcccttcctgtattttgcatgcagaggctgttttaaagttgcaatcagtgttcataaagttcttggcacttccttttttgtacacaagtacattgtaatcattcacctcacggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttg +>frag0007 +agcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccct +>frag0008 +gctggtgaggagctggatccaggaacacaccccaggctctggcctcgggaggagtgtgctgagcttgttgcggagcaaagacagaagcccagtgaacaaaagatggcgaagagaccccagtgctgggaggccaggggtgcagaggccgagtggggctgtgctcaaaagagaggcggtgctggagggacagggagaggtggcctgggtgttgggaggtgggggtgaggtgggggctgagggcaggagggtcagggtgagggataggaaaggccacaggagaggagaggatgaagagctgtgctggaggggctgtgggcagcatcgtcctgctcttgggcactttgtgttttgtgacacatcctttctatgctgaactgaggagccagggacctcactgtccccacacgtgtctgtccaactccagaggatgaagccgagaccacccaagcagtg +>frag0009 +ccaaagagcaagagggtgaccctcccacggctcccaccctggggctgccatcatccactcacccgtcaccccaatgacagagatggggcccacgcgctggccaccgtggaagccgtacaggttcatcttgtatttatggtctggctccaggcctgagatggtgaccccgtcctcgtgccccggcacccgcaccgccttgggctgcccatccccattcctgtactggaccaggaagtggtcaaactggccctcgggaaccgtccaggacaggctgagggagtcaggggtggcatctgtcatggtcagctcccccaggcgaggcttgatggggggctcaggggtcatggtaggcactgcttgggtggtctcggcttcat +>frag0010 +tggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaa +>frag0011 +atgctctttctagcctcctggcctttgcaccagctgtgattatctgacacacttcaccttctctctaaagctgtcaccaagctaaggcatgcctggcctcaggtcctggctgtcccctgggtacccatgggcagggtgacttaggcgtccctgtctggtcctgacctgagccctgggcctccctatcacatgctcacccgcctttgcttcatttgctggattgcagcctgtctctccatgacatgtctttccataatgttgctatattcctttcactgtgagccccatcaagacagaaatatgtataggaaaatggtagagaagggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaac +>frag0012 +tgtcagttgagcaggaccacccagccccaagaatgggcttttctgaaatgacctcacatacccagtagtggccatggtttctccctccttcccttgaagacctgagcacatcccccaggcacctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgta +>frag0013 +gaattctttgctgaatgaacaaattggcccattggtgagaaaggtctgttcctattcctattccaatagtgggcttccagagtgtgcagtcgacgcgctgcccctcactgccttctgtcttccttcacggcccctagtcaactccacagagaaagcacactaccaggaatcagggacgcagaaaaattctcttcaacagatttcaaaagagggtccaattcctttgtcgtgaagaactttgctactcaaggggcgtgatcatgggccagcagcatccgcatcatttcttgttggaaatgcgagaatctctggccctagcccaaacctgttgaaccccaatctgcctcttagcaagatccccaagcatggaaacgtgcaaaagaagcccggctggtgagaatatttttgttttcatgaagttgcagagaaagcaacatcttctagggccatcttcctcact +>frag0014 +attaattttgttatagtgctttcaccgcaacgcatcaaataaccattgaaacgatgatgaatgctggttgtgtagccgtgaggtgaatgattacaatgtacttgtgtacaaaaaaggaagtgccaagaactttatgaacactgattgcaactttaaaacagcctctgcatgcaaaatacaggaagggaatgtgcactacacacattgttattaatgccggcagctgggggagaaagtaggactatgagattcttgttttctgtttttcaagctttccacataatgttgctgtattattttcactagaaaaacgtgggctaaaaaagaaattctgggctgggagcagtggttcacgcctgtaatcctagcattttgggaggccgaggcgggtggatcacctgaggttgggaattc +>frag0015 +tttcaaaagagggtccaattcctttgtcgtgaagaactttgctactcaaggggcgtgatcatgggccagcagcatccgcatcatttcttgttggaaatgcgagaatctctggccctagcccaaacctgttgaaccccaatctgcctcttagcaagatccccaagcatggaaacgtgcaaaagaagcccggctggtgagaatatttttgttttcatgaagttgcagagaaagcaacatcttctagggccatcttcctcactcacaaacactcacctgtcacacccacggtggacaccgggcccacacgccgcccct +>frag0016 +ctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgtacggcctccacgaggggcggcgtgtgggcccggtgtccaccgtgggtgtgacaggtgagtgtttgtgagtgaggaagatggccctagaagatgttgctttctctgcaacttcatgaaaacaaaaatattctcaccagccgggcttcttttgcacgtttccatgcttggggatcttgctaagaggcagattggggttcaacaggtttgggctagggccagagattctcgcatttccaacaagaaatgatgcggatgctgctggcccatgatcacgccccttgagtagcaaagttcttcacgacaaaggaattggaccct +>frag0017 +ctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgagaattactttggctcctgacactatgtctcagttgccttctggaggtttctaacagtgcagctctgccagcagtacagtcgggggctcggggatacctcaccggctcttattccaagagtcactgaacggcgaactcaaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggca +>frag0018 +cctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccagggccacttcgactccttcaccgtgcagtacaaggacagggacgggcggccccaggtgatgcgtgtcaggggcgaggagagcgaggtcaccgtggggggcctggagcccgggcgcaaatacaagatgcacctgtacggcctccacgaggggcggcgtgtgggcccggtgtccaccgtgggtgtgacaggtgagtgtttgtgagtgaggaagatggccctagaagatgttgctttctctgcaacttcatgaaaacaaaaatattctcaccagccgggcttcttttgcacgtttccatgcttggggatcttgctaagaggcagatt +>frag0019 +gccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggat +>frag0020 +aaggaagtgccaagaactttatgaacactgattgcaactttaaaacagcctctgcatgcaaaatacaggaagggaatgtgcactacacacattgttattaatgccggcagctgggggagaaagtaggactatgagattcttgttttctgtttttcaagctttccacataatgttgctgtattattttcactagaaaaacgtgggctaaaaaagaaattctgggctgggagcagtggttcacgcctgtaatcctagcattttgggaggccgaggcgggtggatcacctgaggttgggaattc +>frag0021 +gatggggtggcagggagcctggaggcagcgaggccagtaggcagttggtggccctggtgagaggtgacagtggctcaaactaggatcggggactggaggtggggtaggaaggtatccaggggaattcagggtaaagatgctctgaggctgctggcagctggtgaggagctggatccaggaacacaccccaggctctggcctcgggaggagtgtgctgagcttgttgcggagcaaagacagaagcccagtgaacaaaagatggcgaagagaccccagtgctgggaggccaggggtgcagaggccgagtggggctgtgctcaaaagagaggcggtgctggagggacagggagaggtggcctgggtgttgggaggtgggggtgaggtgggggctgagggcaggagggtcagggtgagggataggaaaggccacaggagaggagagga +>frag0022 +acggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttgtgttcctgacacatctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgagaattactttggctcctgacactatgtctcagttgccttctggaggtttctaacagtgcagctctgccagcagtacagtcgggggctcggggatacctcaccggctcttattccaagagtcactgaacggcgaactca +>frag0023 +gtctctccatgacatgtctttccataatgttgctatattcctttcactgtgagccccatcaagacagaaatatgtataggaaaatggtagagaagggcacattttctagggctgtcttccaaccctgccccacccacactcactcacctgtgacgcccacggcagacaccgggcccaggcgccgcccctcgtggaggccgtacaggtgcatcttgtacttgcgcccaggctccaggcccctcacagtgaccttgctctcctggcccccaacacgcaccgcctggggccgcccgtccctgtccttgtactgcacggtgaaggagtcaaagcggccctgggggacggtccaggaaaggctcagcgagtcaggggaggatcctgtcactgtcagctcccccaggagaggctcctcggggggccctggggctctgtgcctggttctgtagggctgggggtctc +>frag0024 +gccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctc +>frag0025 +caccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtcaggagctctgctgtgctggtggctgtcccagacccccacagctgaccctggaacttgtcatgtgtgttagctgtcagttgagcaggaccacccagccccaagaatgggcttttctgaaatgacctcacatacccagtagtggccatggtttctccctccttcccttgaagacctgagcacatcccccaggcacctggcatcctctctatatctccttttctcagctgcagaggaagagacccccagccccacggaactcagcactgaggccccggagccccctgaggagccgctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctctcctggaccatcccccaggg +>frag0026 +aatctcatagtcctactttctcccccagctgccggcattaataacaatgtgtgtagtgcacattcccttcctgtattttgcatgcagaggctgttttaaagttgcaatcagtgttcataaagttcttggcacttccttttttgtacacaagtacattgtaatcattcacctcacggctacacaaccagcattcatcatcgtttcaatggttatttgatgcgttgcggtgaaagcactataacaaaattaatcatcttctacgggtcatttgtgttcctgacacatctgctgtcatgaataaccccatcgtgagttcttccatgctataactttttcctgctttaataattttcttaggacagatgcccagaactgggattattgggtcaaaggaaatgag +>frag0027 +gcatttccaacaagaaatgatgcggatgctgctggcccatgatcacgccccttgagtagcaaagttcttcacgacaaaggaattggaccctcttttgaaatctgttgaagagaatttttctgcgtccctgattcctggtagtgtgctttctctgtggagttgactaggggccgtgaaggaagacagaaggcagtgaggggcagcgcgtcgactgcacactctggaagcccactattggaataggaataggaacagacctttctcaccaatgggccaatttgttcattcagcaaagaattc +>frag0028 +gtgcccttctctaccattttcctatacatatttctgtcttgatggggctcacagtgaaaggaatatagcaacattatggaaagacatgtcatggagagacaggctgcaatccagcaaatgaagcaaaggcgggtgagcatgtgatagggaggcccagggctcaggtcaggaccagacagggacgcctaagtcaccctgcccatgggtacccaggggacagccaggacctgaggccaggcatgccttagcttggtgacagctttagagagaaggtgaagtgtgtcagataatcacagctggtgcaaaggc +>frag0029 +ctgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggatgagatactcaccgtaaaggacaccccactcaatcctcagtgcctctcacgtgccatgctctttctagcctcctggcctttgcaccagctgtgattatctgacacacttcaccttctctctaaagctgtcaccaagctaaggcatgcctggcctcaggtcctggctgtcccctgggtacccatgggcagggtgacttaggcgtccctgtctggtcc +>frag0030 +cctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatcc +>frag0031 +tcaaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggcacagagccccagggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcctgggcgcaag +>frag0032 +gtcagctcccccaggcgaggcttgatggggggctcaggggtcatggtaggcactgcttgggtggtctcggcttcatcctctggagttggacagacacgtgtggggacagtgaggtccctggctcctcagttcagcatagaaaggatgtgtcacaaaacacaaagtgcccaagagcaggacgatgctgcccacagcccctccagcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactc +>frag0033 +cacccctgactccctcagcctgtcctggacggttcccgagggccagtttgaccacttcctggtccagtacaggaatggggatgggcagcccaaggcggtgcgggtgccggggcacgaggacggggtcaccatctcaggcctggagccagaccataaatacaagatgaacctgtacggcttccacggtggccagcgcgtgggccccatctctgtcattggggtgacgggtgagtggatgatggcagccccagggtgggagccgtgggagggtcaccctcttgctctttggtgatgactggtggggaatgggccaggggtccggtcagcaccacagacctgcttgtggctggggctccccttggccttcctctgaggctgacccctggctcctcctgagcagggaggggccgtc +>frag0034 +ggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcctgggcgcaagtacaagatgcacctgtacggcctccacgaggggcggcgcctgggcccggtgtctgccgtgggcgtcacaggtgagtgagtgtgggtggggcagggttggaagacagccctagaaaatgtgcccttctctaccattttcctatacatatttctgtcttgatggggctcacagtgaaaggaatatagcaacattatggaaagacatgtcatggagagacaggctgcaatccagcaaatgaagcaaaggcgggtgagcatgtgat +>frag0035 +ttcatcctctggagttggacagacacgtgtggggacagtgaggtccctggctcctcagttcagcatagaaaggatgtgtcacaaaacacaaagtgcccaagagcaggacgatgctgcccacagcccctccagcacagctcttcatcctctcctctcctgtggcctttcctatccctcaccctgaccctcctgccctcagcccccacctcacccccacctcccaacacccaggccacctctccctgtccctccagcaccgcctctcttttgagcacagccccactcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcac +>frag0036 +tcggcctctgcacccctggcctcccagcactggggtctcttcgccatcttttgttcactgggcttctgtctttgctccgcaacaagctcagcacactcctcccgaggccagagcctggggtgtgttcctggatccagctcctcaccagctgccagcagcctcagagcatctttaccctgaattcccctggataccttcctaccccacctccagtccccgatcctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccat +>frag0037 +aaagctgccccagccctcagcctgctctggaggggcgcatttgatgtatgacctctgttgacagcaccagcaaagcaagttgcccttaaacccttaaactctgtatccccctatattacctttcagccccacaagaggatgtggacgagacccccagccctacagaaccaggcacagagccccagggccccccgaggagcctctcctgggggagctgacagtgacaggatcctcccctgactcgctgagcctttcctggaccgtcccccagggccgctttgactccttcaccgtgcagtacaaggacagggacgggcggccccaggcggtgcgtgttgggggccaggagagcaaggtcactgtgaggggcctggagcc +>frag0038 +cctagtttgagccactgtcacctctcaccagggccaccaactgcctactggcctcgctgcctccaggctccctgccaccccatccccatcttcagcccccacggatgagcttcacacaggcacagctgctggggccatctcagcacagacctaggcaaccacaccctcaaccccgggagaccccaggcctagtgagtggtcccctcctctgctcccacacttcaggatgagatactcaccgtaaaggacaccccactcaatcctcagtgcctctcacgtgccatgctctttctagcctcctggcc diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/format.txt b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/format.txt new file mode 100644 index 0000000..dc630e1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/format.txt @@ -0,0 +1,4 @@ +// number of variables, number of clauses and number of literals per clause. +// clause 1 (finalized in 0), if literal < 0 then the literal is negated. + +// clause N (finalized in 0), if literal < 0 then the literal is negated. diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat1.txt b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat1.txt new file mode 100644 index 0000000..f8aa7fe --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat1.txt @@ -0,0 +1,44 @@ +10 43 3 +-4 -1 5 0 +-1 -9 -10 0 +-5 -3 -8 0 +-4 -8 -5 0 +2 6 7 0 +-9 -1 -10 0 +5 -3 -9 0 +1 -3 -5 0 +7 2 -4 0 +-7 3 4 0 +-2 1 -9 0 +-8 1 3 0 +3 6 7 0 +-1 -3 -2 0 +4 7 -2 0 +-8 -7 -3 0 +4 3 2 0 +-5 -4 1 0 +-9 10 -8 0 +-6 2 8 0 +-7 -8 5 0 +-7 -5 3 0 +7 9 -10 0 +1 -6 -3 0 +1 -9 6 0 +10 9 4 0 +-8 3 7 0 +8 7 -3 0 +-8 4 9 0 +8 -5 4 0 +8 10 1 0 +-1 -7 8 0 +6 2 5 0 +6 2 10 0 +2 -6 4 0 +-3 9 -1 0 +9 1 -10 0 +10 -5 -8 0 +-10 6 1 0 +1 7 2 0 +-6 3 2 0 +-1 -9 8 0 +-5 2 -10 0 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat2.txt b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat2.txt new file mode 100644 index 0000000..806241f --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/MAXSAT-instances/sat2.txt @@ -0,0 +1,4301 @@ +1000 4300 3 +881 -647 537 0 +-739 396 282 0 +-43 -487 -52 0 +-643 205 796 0 +939 -885 -829 0 +-361 576 421 0 +-193 904 -238 0 +-940 902 26 0 +-177 -783 257 0 +439 942 675 0 +-794 714 -977 0 +310 -524 523 0 +-762 -494 260 0 +-578 305 502 0 +-805 -630 547 0 +729 855 -76 0 +-168 -754 667 0 +965 -418 93 0 +-668 -824 -495 0 +286 976 339 0 +776 -809 -157 0 +395 -120 838 0 +412 895 703 0 +-472 -479 -19 0 +-65 -918 945 0 +-682 -47 -590 0 +-956 996 316 0 +-969 120 222 0 +809 938 995 0 +-882 131 -976 0 +34 61 -359 0 +475 182 -67 0 +105 -391 986 0 +616 -867 -339 0 +-830 236 752 0 +-415 124 903 0 +-473 585 681 0 +203 -11 380 0 +-874 -126 -568 0 +498 -850 -74 0 +435 -113 -261 0 +-690 542 148 0 +-800 -657 752 0 +-624 269 526 0 +794 177 512 0 +-620 -987 819 0 +292 -87 455 0 +-945 758 946 0 +-723 421 908 0 +131 -977 369 0 +-811 -172 875 0 +971 410 -522 0 +287 474 -157 0 +753 458 491 0 +-265 -653 -269 0 +743 890 -606 0 +-207 555 211 0 +-367 799 403 0 +869 559 -407 0 +33 657 488 0 +834 -663 646 0 +-318 -109 804 0 +-235 572 452 0 +-257 -977 984 0 +386 -388 800 0 +-879 -50 131 0 +91 936 -258 0 +215 -310 -748 0 +911 842 670 0 +-514 442 496 0 +8 -111 35 0 +616 -77 325 0 +266 796 918 0 +-22 -261 -317 0 +-654 827 647 0 +48 -267 -905 0 +-921 418 407 0 +685 930 -196 0 +593 379 212 0 +-407 812 805 0 +-983 -942 919 0 +-138 32 678 0 +-306 764 -898 0 +-752 637 573 0 +916 332 -598 0 +890 350 -859 0 +-216 -821 -218 0 +-497 -981 -276 0 +-681 -893 -12 0 +765 -862 -222 0 +-740 6 666 0 +4 145 -59 0 +825 217 14 0 +135 889 -870 0 +-147 -85 -563 0 +298 -876 929 0 +-341 943 997 0 +329 -258 299 0 +-41 911 -906 0 +439 716 450 0 +-300 709 -704 0 +-363 125 260 0 +-442 776 474 0 +-615 -612 593 0 +233 -271 40 0 +661 248 -981 0 +-549 736 228 0 +565 -795 97 0 +706 -314 881 0 +-513 -476 -125 0 +54 721 822 0 +355 -327 -772 0 +-94 588 284 0 +-977 697 485 0 +-144 560 -671 0 +112 -780 324 0 +649 35 -134 0 +84 912 -265 0 +-705 21 858 0 +-224 -991 491 0 +930 -610 -668 0 +-956 -723 -845 0 +-694 798 527 0 +-208 726 594 0 +-151 311 279 0 +-347 -499 994 0 +679 195 -34 0 +-214 829 -895 0 +771 -106 -532 0 +684 855 942 0 +-323 552 -191 0 +-412 -8 -319 0 +327 -117 702 0 +-752 -663 234 0 +427 -92 846 0 +662 -736 -344 0 +164 774 -856 0 +-303 818 -889 0 +-791 -899 477 0 +-786 626 791 0 +-185 -589 -126 0 +964 314 466 0 +175 -299 -442 0 +-384 -545 -365 0 +-584 -719 -906 0 +901 -305 51 0 +-5 671 -804 0 +-895 417 55 0 +579 -693 586 0 +259 863 -872 0 +-176 -933 213 0 +829 437 24 0 +-322 -321 910 0 +-522 -696 641 0 +-682 -538 202 0 +108 450 798 0 +254 505 663 0 +-672 -420 116 0 +-652 -294 759 0 +-196 987 -572 0 +-219 -576 -261 0 +357 -975 -458 0 +164 -44 726 0 +-508 909 286 0 +-201 97 594 0 +-218 -198 776 0 +669 199 -655 0 +-146 822 360 0 +838 -958 372 0 +733 718 412 0 +-445 835 -924 0 +554 -488 155 0 +365 -834 -230 0 +-735 364 348 0 +540 -162 803 0 +-547 113 374 0 +-242 -569 -572 0 +-121 501 -174 0 +213 -815 -942 0 +370 758 492 0 +889 -733 -256 0 +636 -149 273 0 +543 176 -58 0 +92 941 402 0 +-683 -952 924 0 +788 -686 -56 0 +849 -866 155 0 +-121 837 323 0 +-578 866 277 0 +62 -504 857 0 +192 807 -944 0 +647 -350 -468 0 +816 967 -910 0 +-48 -745 285 0 +-894 -521 -397 0 +374 -616 905 0 +-968 -290 -854 0 +-770 747 -777 0 +610 779 -278 0 +-704 -452 964 0 +51 -774 -681 0 +532 -752 -528 0 +-738 433 -319 0 +17 635 -456 0 +-969 709 390 0 +68 317 -980 0 +-502 95 462 0 +-952 -920 -127 0 +280 -820 102 0 +466 635 -896 0 +446 967 -261 0 +-672 -626 396 0 +-609 392 103 0 +826 383 740 0 +-404 218 281 0 +112 -548 941 0 +-463 -408 975 0 +449 245 748 0 +-657 -752 668 0 +395 -915 739 0 +-246 100 -469 0 +975 388 814 0 +-669 -738 -465 0 +-199 203 336 0 +-85 -167 -662 0 +455 -789 475 0 +514 427 -915 0 +806 -825 -635 0 +720 -228 -179 0 +-941 -82 -700 0 +228 -256 -547 0 +374 732 -204 0 +-927 -79 58 0 +-535 -860 -669 0 +391 674 817 0 +-36 -15 -318 0 +-690 -538 -206 0 +-824 418 685 0 +-981 512 -849 0 +-268 -343 952 0 +-914 -720 -827 0 +173 -697 -115 0 +-95 628 -419 0 +-10 521 -459 0 +-539 236 396 0 +-922 -709 740 0 +-248 -746 679 0 +215 511 503 0 +-799 -121 -631 0 +-438 300 -651 0 +-76 287 135 0 +-566 186 706 0 +944 -756 230 0 +-950 264 -581 0 +113 953 821 0 +270 -214 192 0 +-442 145 -143 0 +-951 -931 349 0 +499 903 331 0 +-618 -654 112 0 +-287 -662 -243 0 +440 -691 -429 0 +-374 -370 -707 0 +-559 -883 -214 0 +988 439 471 0 +-239 -13 -732 0 +-997 593 751 0 +287 324 -135 0 +-624 -341 -298 0 +-796 851 -884 0 +198 -191 -81 0 +-71 -647 -421 0 +840 -87 56 0 +-710 465 -8 0 +-465 787 375 0 +573 524 232 0 +-373 -775 28 0 +7 516 -771 0 +-623 -951 770 0 +-152 841 656 0 +741 387 510 0 +49 287 642 0 +-202 -881 -389 0 +-265 -953 -752 0 +-756 -927 -479 0 +-422 227 25 0 +-162 -663 659 0 +-878 935 999 0 +86 982 -458 0 +781 515 510 0 +225 289 890 0 +929 -495 -377 0 +-857 866 -433 0 +436 221 530 0 +-750 8 -24 0 +-413 860 121 0 +609 375 321 0 +850 950 -27 0 +432 -539 -267 0 +-677 242 326 0 +-157 21 -736 0 +-812 -679 726 0 +787 856 -859 0 +-874 50 626 0 +-884 248 127 0 +-716 84 606 0 +825 382 308 0 +-922 -917 250 0 +625 -410 514 0 +144 -975 -311 0 +-570 115 -736 0 +-20 -584 179 0 +373 -515 -166 0 +705 985 226 0 +-707 816 -140 0 +535 -60 441 0 +800 459 -568 0 +50 -180 630 0 +365 715 -819 0 +17 -379 -454 0 +828 178 -957 0 +-383 -741 -258 0 +-740 -336 736 0 +178 -870 417 0 +375 205 216 0 +402 73 -492 0 +-361 63 -409 0 +-996 -741 152 0 +-981 411 808 0 +-875 -71 -26 0 +-448 627 -161 0 +-25 -808 -657 0 +866 -202 -348 0 +-963 -713 671 0 +-464 -642 215 0 +52 -312 -258 0 +96 -466 945 0 +-303 -957 -152 0 +-451 229 530 0 +-695 -547 835 0 +820 -646 294 0 +410 -921 15 0 +-40 520 837 0 +-610 -90 26 0 +-454 576 539 0 +469 -563 -62 0 +477 -897 -272 0 +394 -395 650 0 +551 318 -99 0 +406 -498 361 0 +-219 -348 -116 0 +551 82 -262 0 +-684 487 505 0 +-806 -903 -348 0 +-289 56 587 0 +-780 231 667 0 +-452 -44 68 0 +-586 96 -107 0 +-672 470 242 0 +178 287 46 0 +-648 -366 263 0 +777 126 435 0 +939 -289 -364 0 +830 -176 883 0 +-772 890 803 0 +-68 -429 -616 0 +659 -54 -227 0 +-502 53 999 0 +-430 -909 129 0 +-716 -970 -554 0 +57 -256 242 0 +-152 -255 -478 0 +-347 127 918 0 +127 328 368 0 +731 866 -936 0 +561 331 -525 0 +545 -188 -504 0 +919 765 -243 0 +-724 -864 -492 0 +645 425 -299 0 +949 -38 -968 0 +84 17 202 0 +-884 -28 -736 0 +-1 -410 -464 0 +493 467 -755 0 +642 -759 830 0 +-455 543 -47 0 +-523 885 -72 0 +-761 751 -575 0 +129 9 -836 0 +-621 -59 756 0 +-392 203 -919 0 +200 347 31 0 +-605 -359 525 0 +-869 -339 827 0 +871 -493 79 0 +721 -892 -406 0 +-140 -934 -96 0 +764 -796 -245 0 +365 1000 60 0 +-922 517 -990 0 +893 704 122 0 +819 -586 957 0 +170 184 491 0 +-72 664 381 0 +-1000 295 -918 0 +-868 525 -309 0 +534 -189 210 0 +461 -432 -990 0 +-605 71 -826 0 +527 -317 990 0 +974 -516 -442 0 +-443 -137 -84 0 +-713 -181 -555 0 +626 945 -996 0 +255 685 -306 0 +214 744 -786 0 +-183 -19 -812 0 +-704 472 678 0 +-321 -540 83 0 +277 953 128 0 +-693 -432 -452 0 +-59 -145 41 0 +135 -220 -865 0 +-601 122 -557 0 +-162 -877 238 0 +-373 -649 -579 0 +982 -445 -623 0 +-172 797 687 0 +138 -288 -868 0 +221 668 -570 0 +180 254 -469 0 +39 -766 657 0 +56 -465 773 0 +599 -183 127 0 +-263 81 169 0 +-74 432 -813 0 +-487 -756 -126 0 +-288 -285 -552 0 +-873 52 760 0 +221 631 -550 0 +-812 -310 -242 0 +-328 -141 -278 0 +-792 441 41 0 +51 983 -547 0 +-993 -150 -613 0 +352 564 -483 0 +123 389 -989 0 +-52 830 -364 0 +680 -189 46 0 +-241 634 -130 0 +-720 -401 -297 0 +731 -349 -736 0 +6 -452 8 0 +927 -875 911 0 +309 344 -112 0 +-326 610 -426 0 +843 -699 978 0 +546 118 856 0 +-397 -455 262 0 +653 914 -500 0 +480 848 130 0 +-304 679 672 0 +-765 984 -907 0 +-847 425 -46 0 +199 -727 -716 0 +-350 -281 -804 0 +394 851 -540 0 +-267 -334 -282 0 +339 754 558 0 +-835 -603 155 0 +628 -96 832 0 +-532 899 142 0 +-51 909 -248 0 +-913 20 -577 0 +-688 668 -529 0 +-725 430 198 0 +-887 -454 849 0 +-753 39 177 0 +-584 104 -805 0 +75 296 983 0 +-28 919 -18 0 +68 -848 -550 0 +185 -922 415 0 +-762 873 -367 0 +181 -79 -468 0 +709 -685 410 0 +600 553 -718 0 +-568 -757 309 0 +483 682 -439 0 +-923 847 -668 0 +-513 -668 392 0 +304 -813 880 0 +410 -179 -943 0 +205 -615 -377 0 +354 -131 -917 0 +614 -715 -891 0 +-150 -794 -375 0 +-970 376 325 0 +514 -584 -824 0 +-311 -847 -247 0 +919 -867 433 0 +273 872 -788 0 +958 9 -279 0 +-674 546 -261 0 +-954 678 -774 0 +-739 232 -328 0 +-196 -416 272 0 +338 921 900 0 +-655 -872 -286 0 +-232 -974 399 0 +-772 -199 -428 0 +-553 -778 306 0 +289 -84 151 0 +-483 866 -897 0 +-399 692 844 0 +-35 423 624 0 +-461 -88 -231 0 +-211 -956 -462 0 +-966 -994 40 0 +990 -149 813 0 +-228 853 913 0 +39 -330 -785 0 +-942 -726 -9 0 +-754 -122 -194 0 +539 503 710 0 +-123 461 -815 0 +425 -169 362 0 +3 -954 -383 0 +-538 -374 -8 0 +217 -318 51 0 +299 -499 -919 0 +-452 -121 -674 0 +211 -463 980 0 +-342 563 514 0 +839 691 814 0 +8 646 -632 0 +-487 -231 -401 0 +-479 -206 335 0 +-629 852 354 0 +950 -48 -406 0 +954 -977 415 0 +-315 -858 866 0 +-912 -799 -376 0 +-509 519 964 0 +-550 99 -996 0 +-173 342 483 0 +-677 -525 -828 0 +933 858 23 0 +425 166 -174 0 +-879 -970 -171 0 +618 -303 -364 0 +-76 507 512 0 +762 -604 947 0 +-188 256 -232 0 +730 -854 811 0 +338 -535 606 0 +-24 -772 102 0 +-132 -947 -454 0 +993 -344 476 0 +596 -856 -965 0 +-814 70 -553 0 +229 659 751 0 +38 473 696 0 +928 222 337 0 +-795 -524 -700 0 +-183 281 -516 0 +-169 249 -378 0 +394 -292 941 0 +-200 -806 -739 0 +33 777 358 0 +92 -168 162 0 +-995 -880 -189 0 +181 -495 428 0 +358 45 849 0 +-579 275 -391 0 +116 -466 -982 0 +923 513 -194 0 +-965 -325 -741 0 +-238 -655 643 0 +767 246 257 0 +-199 -826 -318 0 +-728 656 -603 0 +-395 -279 885 0 +259 -342 63 0 +-370 -928 -388 0 +556 544 348 0 +-886 115 788 0 +70 -668 690 0 +-55 -680 -474 0 +814 457 899 0 +-15 239 953 0 +249 184 -6 0 +-608 611 735 0 +-761 468 324 0 +60 -86 -731 0 +363 38 105 0 +-53 -780 953 0 +-140 953 -163 0 +464 -410 438 0 +221 151 438 0 +98 415 698 0 +36 489 -655 0 +998 332 580 0 +-326 -971 105 0 +927 -857 499 0 +-677 -593 -779 0 +-622 -24 457 0 +-22 452 364 0 +-844 -647 194 0 +-101 -348 36 0 +115 -547 970 0 +-202 -261 -878 0 +272 -286 -125 0 +-722 -773 -601 0 +-796 250 273 0 +-834 -265 766 0 +-799 773 -680 0 +-296 841 980 0 +-902 -855 -699 0 +-301 -130 238 0 +799 -916 917 0 +-944 -681 731 0 +606 729 751 0 +649 67 582 0 +-267 -909 -979 0 +816 -889 650 0 +-716 -205 228 0 +530 -161 302 0 +175 823 -319 0 +-344 -944 -701 0 +433 272 -254 0 +94 113 -130 0 +806 -399 -508 0 +-880 897 -456 0 +-288 602 -793 0 +-999 92 362 0 +98 581 698 0 +-994 -428 -524 0 +-565 -967 -848 0 +97 814 -999 0 +842 -904 -899 0 +-61 627 437 0 +340 -977 371 0 +-220 302 336 0 +831 -591 251 0 +107 957 -949 0 +-552 -601 988 0 +-630 348 167 0 +-519 -587 404 0 +783 809 -377 0 +345 -315 -918 0 +-904 346 584 0 +-785 -201 -381 0 +-679 854 -334 0 +-117 367 836 0 +-274 -329 891 0 +-940 429 22 0 +341 -974 768 0 +-972 494 14 0 +-988 -457 -613 0 +997 -391 607 0 +-188 667 -874 0 +-468 814 927 0 +950 -677 -438 0 +-839 -469 691 0 +184 918 401 0 +-236 500 697 0 +-488 -595 -274 0 +390 -536 -162 0 +317 907 -247 0 +928 899 -770 0 +962 872 341 0 +-717 14 1000 0 +-805 -635 535 0 +-950 720 -883 0 +32 -360 390 0 +-176 -541 503 0 +-394 -550 279 0 +-387 -913 228 0 +-125 89 93 0 +329 99 -136 0 +435 -938 39 0 +856 -304 -915 0 +452 -818 129 0 +-18 -532 -493 0 +794 -408 -714 0 +-428 38 983 0 +992 609 -295 0 +-390 -477 574 0 +197 884 -530 0 +-79 -955 -958 0 +142 -455 465 0 +601 953 -622 0 +478 -678 947 0 +-443 -778 2 0 +608 -893 696 0 +421 565 300 0 +-164 140 -726 0 +-299 -320 214 0 +-237 1000 70 0 +136 -886 -613 0 +-145 802 692 0 +822 -641 -939 0 +-631 343 822 0 +554 -679 621 0 +176 432 523 0 +125 181 -41 0 +422 809 845 0 +691 -625 -281 0 +-605 967 -687 0 +809 155 -45 0 +-350 510 -722 0 +747 -816 -758 0 +301 -392 -3 0 +198 -856 -397 0 +-304 965 808 0 +-120 -412 641 0 +95 -903 702 0 +146 -932 776 0 +-231 -163 -696 0 +682 668 -939 0 +-819 460 451 0 +57 -799 -592 0 +-391 453 769 0 +-381 -877 -983 0 +686 595 68 0 +-800 -485 39 0 +396 803 821 0 +-727 -988 -37 0 +-883 66 805 0 +-966 432 -977 0 +-786 468 192 0 +-849 24 -514 0 +-67 690 153 0 +-526 -518 442 0 +27 631 -245 0 +701 211 -58 0 +514 243 904 0 +58 483 956 0 +-815 -870 -158 0 +-296 993 -476 0 +-913 -581 -512 0 +-497 -11 -2 0 +-127 118 767 0 +-655 -302 -514 0 +273 293 395 0 +145 -390 338 0 +-716 117 -563 0 +273 172 256 0 +449 -693 -283 0 +19 -907 -97 0 +-237 -163 -509 0 +99 -813 886 0 +924 3 51 0 +-107 -314 515 0 +-907 184 367 0 +850 539 800 0 +-457 714 420 0 +411 -604 367 0 +643 -791 636 0 +-613 -888 500 0 +526 -605 47 0 +-431 947 930 0 +-660 -860 148 0 +-129 269 753 0 +-488 130 -958 0 +-772 491 422 0 +-910 -339 461 0 +13 -143 504 0 +-414 406 643 0 +-284 182 772 0 +-271 211 -577 0 +946 139 114 0 +-524 -463 108 0 +-424 -688 111 0 +317 780 -384 0 +-3 -50 -678 0 +719 -15 969 0 +-287 -899 -66 0 +-74 187 -865 0 +-346 794 910 0 +869 -166 121 0 +347 -540 224 0 +-26 -281 600 0 +-849 -788 -906 0 +-880 -348 -128 0 +-19 904 -430 0 +715 -377 490 0 +406 230 675 0 +-495 -110 615 0 +474 315 180 0 +-883 672 -444 0 +578 -534 -662 0 +711 -112 -400 0 +-659 642 -144 0 +-693 676 52 0 +-258 716 997 0 +-38 -436 729 0 +-87 -622 -369 0 +516 309 4 0 +-425 657 -965 0 +870 -441 714 0 +-512 822 678 0 +-942 -982 -868 0 +-609 -78 -679 0 +44 -405 -463 0 +-334 -663 -534 0 +413 510 -451 0 +-846 865 475 0 +-559 -765 957 0 +178 222 -276 0 +-437 -645 -369 0 +-936 768 -601 0 +57 -136 554 0 +-374 28 -583 0 +-355 -926 -539 0 +-696 -381 -329 0 +243 720 287 0 +529 811 -790 0 +-961 889 -611 0 +113 542 89 0 +804 -345 532 0 +894 295 508 0 +-606 -894 70 0 +-898 -441 499 0 +-124 -372 -948 0 +223 -909 914 0 +-389 271 782 0 +345 -421 -32 0 +-137 771 -230 0 +587 -689 74 0 +642 351 -523 0 +-255 -297 673 0 +997 656 108 0 +-726 603 442 0 +390 -864 -452 0 +400 -532 -627 0 +215 876 656 0 +945 250 235 0 +651 -754 890 0 +254 -511 516 0 +53 623 -605 0 +500 798 696 0 +170 -84 933 0 +210 -168 150 0 +-765 871 514 0 +532 -793 -440 0 +-320 661 54 0 +422 121 -372 0 +-498 -693 -1 0 +-743 -352 327 0 +-917 -673 -251 0 +-172 -155 -598 0 +-356 -50 627 0 +-512 -498 46 0 +336 181 -852 0 +-585 -393 -178 0 +-849 -222 -478 0 +-677 -471 -645 0 +-729 -432 -517 0 +-147 -571 -730 0 +259 -368 270 0 +-461 524 -696 0 +-316 -700 758 0 +174 -966 -342 0 +-586 -16 114 0 +-208 -123 -490 0 +-864 851 -818 0 +-690 -524 -778 0 +301 -541 855 0 +664 -200 196 0 +-609 -207 452 0 +-991 451 -897 0 +429 168 954 0 +399 343 -962 0 +801 252 -200 0 +-457 -499 -480 0 +726 -1000 83 0 +675 -498 771 0 +282 631 394 0 +666 -595 90 0 +573 -538 121 0 +98 -901 925 0 +781 245 440 0 +-747 680 53 0 +557 -113 -787 0 +666 257 751 0 +-445 -232 251 0 +-582 -754 382 0 +-849 -303 255 0 +-950 -420 -313 0 +181 -5 29 0 +-16 -298 -965 0 +94 -785 -598 0 +618 -326 -549 0 +-337 474 283 0 +-476 -696 -349 0 +658 -423 526 0 +-973 880 943 0 +420 847 794 0 +565 833 -352 0 +254 755 312 0 +27 323 338 0 +709 996 479 0 +-636 851 -680 0 +102 -873 -263 0 +903 982 -37 0 +424 -366 805 0 +-468 755 638 0 +380 48 586 0 +427 212 414 0 +178 354 -673 0 +-156 -558 -192 0 +-670 -106 383 0 +-127 838 857 0 +195 -973 -987 0 +994 -891 112 0 +850 542 -238 0 +-124 -382 772 0 +-177 332 494 0 +-844 -511 818 0 +-843 -108 -721 0 +982 -463 899 0 +298 -810 -232 0 +-147 -17 -774 0 +-383 -592 748 0 +368 -321 882 0 +35 473 -855 0 +-578 927 654 0 +-620 683 694 0 +781 -54 169 0 +742 -256 -115 0 +622 -387 -123 0 +380 364 234 0 +133 659 80 0 +260 632 -265 0 +990 -596 -966 0 +944 694 995 0 +774 -212 -504 0 +-906 168 -75 0 +5 824 886 0 +55 982 34 0 +313 -87 -257 0 +792 575 586 0 +76 439 35 0 +449 542 330 0 +-95 111 971 0 +-433 -726 802 0 +-605 992 596 0 +-655 856 -631 0 +-413 600 -606 0 +165 843 -5 0 +883 -481 -210 0 +-579 -21 -533 0 +-232 -44 125 0 +434 -776 -171 0 +-509 -279 -29 0 +-910 795 -564 0 +-417 915 216 0 +67 983 -871 0 +565 -855 -675 0 +110 -387 461 0 +602 -88 -294 0 +-40 781 -826 0 +-996 612 -440 0 +916 -446 -606 0 +-947 684 -618 0 +48 694 7 0 +-497 866 58 0 +-915 77 710 0 +445 95 594 0 +710 682 -379 0 +581 -551 -419 0 +-873 -536 917 0 +-267 -794 51 0 +-890 -20 521 0 +969 104 529 0 +130 -929 237 0 +-426 216 93 0 +225 301 -589 0 +-825 -461 -918 0 +-426 82 901 0 +-878 185 -992 0 +510 -136 -850 0 +399 288 883 0 +-334 4 -807 0 +610 -512 -685 0 +-550 556 12 0 +-788 -492 8 0 +-473 190 -244 0 +-63 -446 598 0 +-774 -933 -219 0 +928 -311 -600 0 +-466 265 322 0 +817 -869 -57 0 +-887 940 63 0 +-603 862 -109 0 +-711 -845 -143 0 +415 226 192 0 +-275 321 607 0 +-954 312 600 0 +944 -377 -353 0 +320 -404 820 0 +58 -958 -858 0 +225 -289 -278 0 +-185 -797 -914 0 +486 123 895 0 +-863 -769 -812 0 +452 -322 -621 0 +-604 -591 649 0 +473 818 993 0 +265 912 150 0 +540 -107 -3 0 +3 -326 -128 0 +181 814 -41 0 +-646 -606 196 0 +-29 305 -547 0 +-966 -282 -398 0 +905 -994 -465 0 +89 -883 698 0 +724 -706 767 0 +691 -575 81 0 +-835 180 176 0 +-489 -205 585 0 +-718 -198 -28 0 +759 -647 406 0 +-740 -89 187 0 +-231 529 -319 0 +548 -387 406 0 +613 950 538 0 +-719 -331 -520 0 +616 728 871 0 +538 425 865 0 +-504 336 -716 0 +-497 274 133 0 +557 -132 -809 0 +-911 -226 -128 0 +484 -390 609 0 +-191 -396 81 0 +739 444 788 0 +-619 350 107 0 +-298 560 1000 0 +-179 -243 154 0 +476 -979 886 0 +275 -606 -674 0 +-495 220 -340 0 +-38 -653 14 0 +27 -676 832 0 +-121 820 403 0 +815 726 -337 0 +-409 878 -750 0 +-458 -618 129 0 +-619 -294 625 0 +-504 201 526 0 +394 447 974 0 +-774 -371 6 0 +589 -641 -846 0 +-803 257 934 0 +-516 -909 -306 0 +714 521 -782 0 +445 -19 -48 0 +627 -174 -483 0 +-257 -39 -527 0 +-873 762 -609 0 +445 -575 -844 0 +61 580 -816 0 +-86 578 317 0 +-35 -244 -127 0 +312 -836 786 0 +106 600 425 0 +-417 373 724 0 +98 -354 339 0 +482 -465 580 0 +-99 -730 311 0 +300 501 8 0 +-118 -332 -680 0 +-272 351 918 0 +94 798 833 0 +743 693 454 0 +560 656 -842 0 +-18 175 -643 0 +592 -423 830 0 +723 23 -507 0 +155 342 307 0 +-113 -738 454 0 +77 -430 -740 0 +171 283 -262 0 +-907 -866 -853 0 +-370 -881 429 0 +726 522 -817 0 +360 225 -648 0 +-974 47 492 0 +-993 -103 330 0 +-572 592 131 0 +-588 295 193 0 +-240 -954 -787 0 +941 797 417 0 +-263 245 326 0 +-227 -317 -550 0 +114 539 309 0 +204 223 -420 0 +538 400 -602 0 +-630 47 500 0 +-293 -59 189 0 +-599 50 -501 0 +-615 772 928 0 +-1000 343 -494 0 +953 189 -451 0 +-310 349 317 0 +86 427 151 0 +-577 -685 318 0 +-264 732 337 0 +-130 816 -496 0 +-784 -994 -921 0 +-258 128 277 0 +158 -86 -992 0 +-335 -683 -537 0 +720 901 -244 0 +863 -290 163 0 +-501 368 -681 0 +-221 -127 -1 0 +-584 677 -864 0 +981 -370 -623 0 +-114 602 -63 0 +-198 322 -981 0 +907 -533 -124 0 +153 299 -836 0 +-70 -659 -575 0 +-806 694 -823 0 +-333 -628 -151 0 +95 212 46 0 +259 575 -809 0 +228 902 -894 0 +-308 981 448 0 +-153 -341 20 0 +92 616 966 0 +326 -743 -859 0 +328 -843 347 0 +653 -428 -401 0 +212 717 -475 0 +306 -976 -469 0 +462 -974 -653 0 +379 -310 437 0 +712 -698 -483 0 +-989 126 -848 0 +478 -92 -769 0 +515 878 774 0 +-763 494 605 0 +399 314 122 0 +118 759 -195 0 +-61 905 -917 0 +-774 550 -693 0 +-657 -222 263 0 +-923 665 352 0 +655 -267 -936 0 +-297 -442 -448 0 +-347 -866 -174 0 +630 -866 -116 0 +-429 628 -274 0 +-751 -630 -352 0 +-9 666 -468 0 +-544 -140 -594 0 +356 705 506 0 +-645 -248 546 0 +-643 338 -37 0 +148 684 522 0 +475 336 -315 0 +198 302 194 0 +919 -795 921 0 +24 607 145 0 +-316 593 -52 0 +761 -292 -37 0 +456 766 682 0 +-814 -294 348 0 +-940 417 722 0 +712 -131 465 0 +-987 -449 -78 0 +987 -639 824 0 +288 -314 458 0 +686 528 -813 0 +-539 -282 81 0 +32 889 937 0 +579 -161 281 0 +-768 -518 626 0 +-386 -130 866 0 +-721 736 -414 0 +-137 725 -275 0 +140 -157 293 0 +-257 -183 -90 0 +832 -404 -111 0 +-123 -955 -792 0 +-149 999 66 0 +-660 -659 -151 0 +80 243 -258 0 +972 -247 -865 0 +436 961 254 0 +-120 -251 -492 0 +744 618 -748 0 +867 36 -93 0 +-629 -793 345 0 +-443 542 -187 0 +-40 -358 -592 0 +634 806 -122 0 +363 316 -634 0 +-229 338 -451 0 +-452 -798 391 0 +-29 174 -585 0 +15 -609 -136 0 +-751 659 -813 0 +-45 962 -593 0 +-475 439 -271 0 +-949 858 631 0 +931 233 917 0 +-824 74 -274 0 +529 -560 -464 0 +-355 892 -526 0 +193 787 734 0 +-949 583 727 0 +675 -296 -745 0 +652 279 639 0 +314 241 -815 0 +-227 -578 919 0 +653 -278 -718 0 +986 46 -146 0 +974 -651 693 0 +206 781 -523 0 +284 -712 930 0 +-977 458 -497 0 +-80 -825 769 0 +-578 85 -297 0 +202 420 -852 0 +-231 -589 -38 0 +-542 553 -661 0 +-258 -979 36 0 +59 821 159 0 +949 148 -411 0 +-469 383 -200 0 +-466 342 -232 0 +790 211 160 0 +-525 363 -196 0 +695 -77 -2 0 +123 -639 19 0 +-200 636 -671 0 +-898 19 798 0 +-593 -496 -32 0 +267 -125 91 0 +-98 -188 623 0 +602 685 -198 0 +-69 875 -387 0 +825 -289 227 0 +-285 -551 753 0 +875 -178 -57 0 +-682 -686 614 0 +-614 756 -241 0 +-654 -736 235 0 +-743 -845 375 0 +-893 763 246 0 +406 -233 610 0 +468 100 466 0 +-705 293 43 0 +-724 -697 634 0 +-517 -184 -743 0 +327 849 227 0 +694 869 -145 0 +447 222 975 0 +-512 -834 609 0 +258 -423 -681 0 +204 584 925 0 +532 27 -920 0 +-402 -786 938 0 +807 -401 -373 0 +-492 812 526 0 +-988 779 -926 0 +60 -858 -774 0 +340 -277 -547 0 +-747 329 601 0 +610 -826 624 0 +930 -596 -227 0 +395 742 563 0 +-171 970 396 0 +-655 -664 -701 0 +284 103 275 0 +-758 -824 -979 0 +191 868 891 0 +-290 -479 108 0 +410 -576 -176 0 +-473 223 -956 0 +-687 -127 386 0 +145 -189 713 0 +54 49 -507 0 +-700 510 230 0 +993 989 135 0 +843 -454 900 0 +663 478 584 0 +285 -784 288 0 +-199 404 -713 0 +-374 -147 238 0 +-58 21 -893 0 +289 963 -278 0 +-886 642 -185 0 +85 -130 77 0 +-927 210 166 0 +-587 418 145 0 +-652 878 -171 0 +952 207 826 0 +262 -953 -165 0 +-589 -404 174 0 +-878 411 705 0 +549 -187 -469 0 +-332 481 364 0 +155 214 -991 0 +-16 -928 160 0 +849 699 -388 0 +653 831 -22 0 +398 415 768 0 +-805 -288 -201 0 +947 -95 -942 0 +-872 59 553 0 +-386 -223 260 0 +202 82 881 0 +-44 -944 -670 0 +-886 -706 306 0 +-459 -774 -452 0 +-826 -361 -562 0 +-318 -732 512 0 +-716 -791 647 0 +-103 821 153 0 +-858 -938 114 0 +-973 826 870 0 +457 -326 -320 0 +301 808 556 0 +-502 960 146 0 +-456 -88 -144 0 +-915 -856 521 0 +-526 -71 -405 0 +626 24 -395 0 +919 171 191 0 +-122 -60 268 0 +862 -650 -735 0 +117 -511 949 0 +649 797 82 0 +-907 -919 136 0 +644 843 -849 0 +635 213 149 0 +970 204 460 0 +-216 -728 -159 0 +466 -989 693 0 +-106 200 -666 0 +-429 250 -980 0 +967 465 788 0 +-8 -939 803 0 +605 113 -797 0 +-37 -187 -164 0 +-380 -551 -387 0 +-705 758 800 0 +725 -470 267 0 +-909 -123 -996 0 +568 334 -211 0 +-530 608 551 0 +-615 173 444 0 +-592 -617 -158 0 +-793 684 -373 0 +-706 991 177 0 +727 -9 -204 0 +-608 486 174 0 +532 -570 876 0 +970 490 832 0 +232 884 -162 0 +-439 161 -565 0 +-692 235 -767 0 +437 831 -610 0 +-461 -672 878 0 +-371 -303 -258 0 +937 -162 -795 0 +-996 599 -98 0 +813 -466 395 0 +440 -851 469 0 +-64 -432 -555 0 +921 875 752 0 +303 -71 474 0 +-445 666 604 0 +-124 380 -322 0 +770 348 341 0 +-371 194 -14 0 +-668 -689 -275 0 +-800 -539 628 0 +419 -727 -587 0 +925 -376 714 0 +579 371 525 0 +539 216 789 0 +-143 87 -927 0 +-878 -248 -479 0 +459 164 -265 0 +522 783 554 0 +924 281 -484 0 +214 -322 779 0 +806 -425 470 0 +-248 518 349 0 +-210 139 -554 0 +3 -426 577 0 +934 659 548 0 +486 576 -801 0 +390 -402 21 0 +184 -113 927 0 +789 708 35 0 +405 -680 -962 0 +606 -958 -268 0 +-268 647 -56 0 +616 -257 221 0 +880 -310 -627 0 +847 501 -515 0 +-495 -289 178 0 +511 789 135 0 +609 -92 438 0 +-141 -357 -74 0 +-762 -434 305 0 +390 257 574 0 +119 199 -231 0 +935 -303 295 0 +871 -692 596 0 +538 -29 588 0 +-776 -502 553 0 +-711 908 -645 0 +879 224 -108 0 +931 -278 369 0 +849 -926 944 0 +854 395 234 0 +943 -46 -430 0 +-993 -624 -80 0 +-152 -868 252 0 +234 -473 -273 0 +370 984 691 0 +454 -708 -934 0 +720 230 967 0 +-941 -56 782 0 +-793 959 863 0 +286 -380 846 0 +-332 502 -455 0 +-66 865 974 0 +-123 -646 -318 0 +-341 -851 -344 0 +750 -837 915 0 +-341 -18 -318 0 +356 -624 -955 0 +-800 -669 500 0 +-700 204 -60 0 +992 -794 -819 0 +273 -734 -715 0 +579 -101 -436 0 +941 640 -156 0 +-802 182 402 0 +578 -763 -740 0 +-541 875 -13 0 +-27 -706 -7 0 +-43 -704 -442 0 +-853 -642 -420 0 +99 -351 664 0 +-293 22 -296 0 +-412 -847 997 0 +114 -709 413 0 +408 -91 323 0 +-502 868 402 0 +-300 122 689 0 +96 179 -814 0 +-308 -399 -289 0 +376 -656 -122 0 +605 -906 -148 0 +14 -495 909 0 +-646 66 -4 0 +959 833 -12 0 +198 -368 -16 0 +414 850 -363 0 +-982 -842 -365 0 +-524 283 -919 0 +-357 802 -733 0 +-772 391 161 0 +-611 239 494 0 +217 211 135 0 +965 -737 501 0 +499 351 112 0 +746 621 102 0 +-574 689 -533 0 +927 -66 -483 0 +316 715 -389 0 +-117 -336 -861 0 +-482 -365 -492 0 +905 -178 -653 0 +-183 812 -820 0 +-422 -555 -483 0 +550 678 -31 0 +282 778 -14 0 +-964 -549 -730 0 +-589 23 -595 0 +13 -923 691 0 +30 356 912 0 +-884 437 -563 0 +13 -996 931 0 +-243 -452 -74 0 +116 549 -237 0 +-222 285 668 0 +261 -888 -458 0 +216 -937 -525 0 +-14 185 119 0 +-785 272 -276 0 +487 -361 443 0 +987 -28 342 0 +-224 -505 -245 0 +620 655 525 0 +442 -103 128 0 +-248 759 81 0 +-762 22 389 0 +552 -145 262 0 +737 520 -131 0 +95 -295 473 0 +-396 -678 518 0 +-827 -55 -863 0 +-432 132 172 0 +-322 94 -33 0 +-290 665 626 0 +-966 275 -284 0 +-835 -508 174 0 +-940 417 175 0 +369 345 -267 0 +-350 429 201 0 +-489 31 185 0 +857 574 47 0 +204 -573 416 0 +-207 -298 220 0 +780 -991 -452 0 +-287 -775 -523 0 +374 484 -596 0 +449 -289 -755 0 +238 564 -251 0 +134 517 -908 0 +-811 540 66 0 +-237 20 -239 0 +934 222 -769 0 +-927 -23 -716 0 +348 981 260 0 +-595 901 537 0 +623 641 -823 0 +126 -620 782 0 +-566 -383 -658 0 +-717 -345 -164 0 +-22 -808 50 0 +613 42 65 0 +568 -207 -976 0 +-225 52 -836 0 +132 -463 -325 0 +-590 -386 -593 0 +634 -53 722 0 +648 -242 -410 0 +-352 -400 -642 0 +-69 -514 143 0 +181 -760 -465 0 +347 -875 -177 0 +882 -983 14 0 +121 103 -992 0 +-734 380 -322 0 +-986 -920 -926 0 +872 -781 565 0 +-800 903 329 0 +588 234 -960 0 +-411 375 584 0 +503 -210 189 0 +-209 767 610 0 +-992 925 622 0 +394 350 96 0 +-163 851 -778 0 +-852 -221 822 0 +796 -21 148 0 +-423 736 150 0 +696 -795 33 0 +-719 778 195 0 +-19 -625 894 0 +132 -883 -183 0 +-699 9 -923 0 +-956 -249 248 0 +-591 160 -988 0 +564 479 -399 0 +552 463 -840 0 +-422 -349 -200 0 +713 687 36 0 +-541 -817 -915 0 +221 552 -288 0 +-890 -578 143 0 +41 669 -195 0 +-35 107 -411 0 +948 -745 51 0 +581 628 719 0 +814 -304 -456 0 +-271 70 492 0 +115 214 -92 0 +216 -885 -306 0 +-942 804 242 0 +-121 716 577 0 +543 -146 -639 0 +-589 404 -435 0 +-590 120 854 0 +663 900 -211 0 +-337 -47 -359 0 +9 -628 -677 0 +-348 -648 -332 0 +680 475 388 0 +742 254 -732 0 +-521 127 466 0 +778 -310 -969 0 +-367 369 991 0 +95 -87 710 0 +741 -956 585 0 +-405 263 140 0 +580 557 54 0 +-121 -946 617 0 +-971 -99 -509 0 +-151 367 240 0 +-239 -522 464 0 +-545 -534 948 0 +373 -197 559 0 +762 907 -263 0 +684 -261 -537 0 +-134 3 -45 0 +558 -150 -902 0 +-296 356 -865 0 +983 581 -892 0 +714 185 -300 0 +576 -696 -504 0 +150 950 -809 0 +-56 420 -15 0 +-92 59 -925 0 +-670 -483 -284 0 +-762 -702 96 0 +975 759 294 0 +-857 -518 142 0 +937 -486 518 0 +-244 -585 -845 0 +-129 -834 216 0 +-439 385 926 0 +-377 29 -922 0 +-989 -502 -303 0 +892 -472 422 0 +-275 -561 26 0 +-747 887 -791 0 +277 -762 111 0 +-967 -891 286 0 +-470 -164 261 0 +762 527 -558 0 +159 -757 553 0 +944 270 558 0 +-398 -3 151 0 +-9 -715 80 0 +436 -15 -947 0 +872 -60 -213 0 +658 298 -787 0 +2 -784 94 0 +461 398 -696 0 +-550 982 -33 0 +199 -645 -154 0 +732 361 617 0 +-515 -386 -115 0 +-105 73 -165 0 +-145 165 48 0 +751 -977 -39 0 +995 -918 -892 0 +772 651 578 0 +110 311 -640 0 +-388 -139 693 0 +493 96 798 0 +-225 600 -253 0 +-226 -574 -530 0 +-86 156 599 0 +379 -15 299 0 +-953 622 967 0 +690 -454 -764 0 +688 -463 -265 0 +-123 -473 -282 0 +580 451 -242 0 +-642 523 -57 0 +-569 561 898 0 +754 -557 228 0 +121 547 734 0 +-133 -329 -314 0 +357 643 45 0 +-576 247 -677 0 +-819 8 -642 0 +312 496 941 0 +678 -196 46 0 +222 622 -17 0 +318 -303 757 0 +239 -649 219 0 +-944 -516 -448 0 +-336 293 290 0 +368 -868 915 0 +-84 11 -373 0 +40 -699 -964 0 +-202 849 -470 0 +627 -951 71 0 +441 238 354 0 +657 517 32 0 +-694 -306 -77 0 +-236 -977 821 0 +-304 -194 61 0 +236 -921 118 0 +-646 -644 691 0 +625 544 202 0 +785 992 -843 0 +504 -494 -713 0 +44 -556 192 0 +788 168 -891 0 +276 -183 940 0 +899 -163 705 0 +-440 172 -863 0 +-378 775 262 0 +285 670 583 0 +-235 35 414 0 +-106 117 -671 0 +999 -213 -140 0 +362 -775 977 0 +-882 197 -734 0 +-820 -969 -873 0 +335 920 740 0 +-919 350 -312 0 +-271 849 -548 0 +-643 -642 5 0 +-150 52 473 0 +-433 455 692 0 +-365 -631 918 0 +-390 -280 -124 0 +70 -544 -976 0 +-193 -235 -163 0 +-803 58 770 0 +-107 817 -323 0 +-67 954 124 0 +516 291 629 0 +-545 760 361 0 +483 591 -141 0 +650 294 -570 0 +-53 -855 -45 0 +57 -940 449 0 +471 -134 843 0 +-618 -732 -452 0 +-895 674 -939 0 +-970 -550 26 0 +220 493 874 0 +-948 159 602 0 +-777 195 898 0 +346 104 802 0 +-77 90 -923 0 +-441 -648 -480 0 +264 288 939 0 +385 780 267 0 +-195 -861 244 0 +143 713 -836 0 +-542 733 -739 0 +-138 -480 837 0 +527 -480 -38 0 +950 252 48 0 +993 -436 812 0 +563 705 -378 0 +-464 369 838 0 +843 378 571 0 +-391 634 680 0 +-799 -626 113 0 +599 -28 -285 0 +155 -210 981 0 +109 545 206 0 +-56 583 601 0 +969 -436 260 0 +-153 629 969 0 +-419 -514 -99 0 +-802 16 -922 0 +478 -996 778 0 +645 -389 -188 0 +-726 718 635 0 +-467 -116 272 0 +-669 105 -302 0 +763 -372 -778 0 +291 226 885 0 +-790 669 99 0 +889 -995 716 0 +130 777 926 0 +907 -699 268 0 +717 -940 718 0 +271 -425 247 0 +-502 -808 -866 0 +514 -958 709 0 +-984 841 16 0 +556 -188 999 0 +771 954 -758 0 +-182 -990 -919 0 +-44 475 -859 0 +-694 -423 -696 0 +296 -945 -131 0 +48 140 775 0 +365 275 615 0 +604 -950 757 0 +-861 -820 -377 0 +-763 -435 696 0 +-3 130 -493 0 +-567 281 -685 0 +-372 609 -445 0 +597 338 -679 0 +-400 588 68 0 +-909 536 -785 0 +455 -275 -102 0 +-362 -693 -529 0 +-709 -239 -513 0 +894 679 888 0 +-163 -479 -470 0 +459 264 -456 0 +-272 325 773 0 +297 -991 -119 0 +378 502 198 0 +-65 -466 57 0 +-411 -381 95 0 +970 862 699 0 +941 585 -538 0 +-239 41 35 0 +659 -210 826 0 +330 260 804 0 +509 80 -343 0 +-244 243 -134 0 +-338 -620 605 0 +698 -213 -768 0 +298 -923 762 0 +-995 41 -763 0 +309 -285 865 0 +996 104 619 0 +-896 -478 660 0 +-800 -904 -404 0 +546 812 101 0 +487 36 186 0 +-689 -218 -646 0 +482 490 304 0 +-503 -946 -116 0 +-722 52 430 0 +-905 -949 505 0 +776 969 866 0 +292 -613 957 0 +-26 -240 515 0 +429 58 -978 0 +149 86 -175 0 +982 -863 -415 0 +960 -343 717 0 +-836 688 102 0 +-762 609 -496 0 +117 630 -979 0 +-334 916 552 0 +-110 253 828 0 +-165 -873 -905 0 +670 -486 -898 0 +400 -529 -651 0 +-240 -334 -981 0 +-728 -869 -271 0 +957 101 -67 0 +226 -679 363 0 +-228 234 899 0 +-420 -43 965 0 +-535 -974 -97 0 +352 -162 737 0 +-141 -723 -553 0 +-76 -936 567 0 +943 -520 88 0 +683 557 827 0 +-939 49 551 0 +-645 -76 -797 0 +386 -913 -167 0 +694 -615 257 0 +-201 -294 154 0 +-492 -108 66 0 +-653 469 158 0 +717 294 444 0 +-881 -528 754 0 +-750 -23 -880 0 +26 578 -83 0 +933 386 742 0 +-913 910 -846 0 +489 -934 721 0 +-756 -611 -208 0 +155 446 977 0 +162 -899 -406 0 +951 355 290 0 +-810 -301 534 0 +618 846 -264 0 +36 755 -636 0 +-820 -709 736 0 +-442 304 -383 0 +449 66 -764 0 +-323 -635 298 0 +65 -624 254 0 +-43 -257 362 0 +348 -199 940 0 +-5 955 626 0 +-242 -3 651 0 +619 235 -881 0 +-203 -908 466 0 +526 874 -221 0 +-935 799 852 0 +618 -427 243 0 +724 -648 64 0 +576 -164 -662 0 +-772 710 -932 0 +986 578 -872 0 +-409 -920 573 0 +-126 499 335 0 +248 -533 -267 0 +-360 -755 862 0 +-811 1 577 0 +-73 -81 419 0 +-278 -367 600 0 +425 155 -186 0 +726 905 926 0 +798 -478 -415 0 +-134 301 -617 0 +709 12 175 0 +744 326 -578 0 +-114 473 79 0 +833 276 577 0 +26 808 -346 0 +-860 414 -158 0 +329 -731 -61 0 +874 -377 903 0 +223 108 -790 0 +-791 215 898 0 +404 341 -186 0 +996 972 490 0 +-126 -518 256 0 +-513 -754 604 0 +176 267 -31 0 +-196 -819 172 0 +834 -11 986 0 +-82 -849 -931 0 +450 746 -60 0 +159 196 615 0 +530 -75 318 0 +562 -316 112 0 +-206 -404 157 0 +-569 289 -530 0 +-152 -201 2 0 +497 749 -639 0 +314 -368 289 0 +698 -899 935 0 +768 -133 239 0 +991 -934 231 0 +-964 742 141 0 +-969 135 94 0 +232 519 158 0 +-547 939 736 0 +-176 202 -160 0 +-748 -999 -473 0 +219 134 -382 0 +666 989 607 0 +-55 87 -355 0 +-800 673 -722 0 +-38 -973 -751 0 +-373 32 787 0 +423 74 217 0 +-515 529 -444 0 +-426 969 378 0 +649 -218 -389 0 +316 767 -901 0 +417 -753 712 0 +-595 -300 635 0 +403 689 569 0 +-130 536 131 0 +-410 -758 621 0 +654 -826 -928 0 +514 210 217 0 +-417 -570 755 0 +-833 -491 945 0 +439 -381 -1 0 +895 183 18 0 +330 682 -26 0 +201 822 -550 0 +-52 269 -817 0 +877 -274 -264 0 +360 -688 172 0 +-43 152 -209 0 +-632 961 327 0 +361 -923 662 0 +739 952 176 0 +-196 -218 371 0 +752 -160 446 0 +-912 -881 168 0 +383 70 792 0 +110 268 -324 0 +719 988 -837 0 +554 127 290 0 +826 626 300 0 +161 28 471 0 +-934 921 -240 0 +-415 -19 -297 0 +-486 -734 114 0 +-839 890 -299 0 +303 565 833 0 +-679 -632 180 0 +582 -439 66 0 +961 -41 -820 0 +-59 594 -151 0 +-426 -422 -826 0 +-107 8 -235 0 +844 958 -838 0 +-210 -243 193 0 +307 258 418 0 +485 -57 492 0 +-150 110 -460 0 +870 320 219 0 +529 -410 885 0 +762 -967 -506 0 +-288 -458 -211 0 +-583 -974 -330 0 +-825 847 457 0 +-496 -597 -548 0 +931 560 334 0 +-457 -290 291 0 +754 796 555 0 +938 359 -334 0 +668 486 782 0 +-361 -678 840 0 +170 -13 213 0 +-808 156 300 0 +-98 -834 461 0 +-58 417 233 0 +-885 -719 144 0 +-193 -485 -392 0 +826 -876 391 0 +165 972 -472 0 +-317 -920 649 0 +839 -697 893 0 +-529 739 -156 0 +-271 -1 -952 0 +286 -535 452 0 +-555 201 -78 0 +-740 -765 -492 0 +62 778 -924 0 +-46 967 -621 0 +592 984 -29 0 +-310 235 262 0 +473 391 -87 0 +1000 -82 717 0 +344 -62 -844 0 +994 -174 -36 0 +-380 591 -160 0 +469 -781 -968 0 +596 -152 780 0 +-773 -133 493 0 +-240 -354 -26 0 +-701 -869 416 0 +-229 181 -618 0 +735 154 982 0 +-212 -277 -928 0 +-220 217 271 0 +-778 -487 -371 0 +350 -657 505 0 +148 11 746 0 +410 27 999 0 +-476 -998 -405 0 +922 507 606 0 +275 752 -410 0 +-510 842 680 0 +805 -316 -960 0 +672 -765 -771 0 +-200 -470 -162 0 +-232 -334 440 0 +593 -757 -676 0 +-6 -971 779 0 +71 -193 -913 0 +28 -832 230 0 +798 659 843 0 +-196 990 -932 0 +95 -37 600 0 +-137 -175 509 0 +20 778 -620 0 +-341 -644 841 0 +19 -235 -55 0 +-96 -828 905 0 +543 -279 218 0 +-939 341 859 0 +137 558 711 0 +-555 678 453 0 +-84 288 -306 0 +-959 510 592 0 +856 793 -623 0 +767 -821 922 0 +444 -810 -325 0 +-12 175 -942 0 +267 979 358 0 +-977 -660 838 0 +-126 840 -92 0 +-44 241 133 0 +-522 361 325 0 +212 921 -756 0 +399 915 945 0 +581 -631 507 0 +998 641 572 0 +585 -670 849 0 +-959 -846 -32 0 +-13 961 24 0 +-942 -807 -923 0 +-975 139 3 0 +-793 164 -591 0 +-496 -802 -512 0 +969 655 -929 0 +463 576 -823 0 +736 937 485 0 +800 496 -963 0 +799 -263 -445 0 +959 708 534 0 +706 -50 -414 0 +-615 339 -50 0 +973 -85 896 0 +559 510 260 0 +-714 783 689 0 +-581 -110 -257 0 +-429 162 -843 0 +285 -951 718 0 +19 -353 -510 0 +302 532 167 0 +-992 -477 -537 0 +-152 844 -819 0 +134 212 -215 0 +643 9 -709 0 +927 -821 443 0 +-101 -680 782 0 +333 440 100 0 +926 192 -269 0 +124 858 -413 0 +-376 151 938 0 +-605 -700 -461 0 +981 103 -770 0 +-258 -575 323 0 +-405 604 -353 0 +418 -485 709 0 +733 595 -892 0 +-845 289 -619 0 +-181 617 -216 0 +302 706 -102 0 +385 -631 -4 0 +805 492 820 0 +-543 -386 -876 0 +-344 -164 -420 0 +-286 841 -779 0 +426 -502 -9 0 +179 923 850 0 +-437 606 -278 0 +365 527 801 0 +-696 -505 517 0 +114 -324 746 0 +-926 204 919 0 +194 922 217 0 +446 -101 75 0 +-188 -287 -60 0 +-962 -856 -744 0 +587 -578 110 0 +-299 439 -728 0 +681 534 815 0 +-2 525 435 0 +286 154 -72 0 +374 121 -858 0 +-816 731 -479 0 +530 973 125 0 +541 835 -841 0 +-764 125 -742 0 +196 600 60 0 +-599 -312 -811 0 +458 -813 853 0 +430 -394 288 0 +400 81 17 0 +338 303 460 0 +108 652 446 0 +-630 507 566 0 +-981 314 635 0 +-800 -586 156 0 +-365 -246 704 0 +-118 -777 802 0 +352 -190 585 0 +921 -720 992 0 +331 486 891 0 +575 554 -577 0 +330 29 98 0 +-245 961 -111 0 +-510 588 799 0 +474 -321 -565 0 +137 -57 839 0 +843 -508 243 0 +342 -242 -315 0 +48 -370 -193 0 +195 -44 168 0 +-796 619 -913 0 +908 965 408 0 +-935 924 259 0 +-644 -817 -387 0 +840 903 456 0 +-737 656 175 0 +177 -355 651 0 +-446 -660 -34 0 +-726 -333 772 0 +842 900 -545 0 +102 456 -143 0 +126 311 897 0 +14 937 106 0 +833 -951 796 0 +-361 -766 -377 0 +-782 -110 -786 0 +-408 -150 -921 0 +-124 -101 467 0 +749 -433 -126 0 +931 446 -485 0 +4 754 890 0 +277 -509 661 0 +263 -271 550 0 +-36 342 -246 0 +832 29 -235 0 +-877 -603 -265 0 +-543 253 -342 0 +-997 -658 957 0 +572 360 742 0 +-960 350 739 0 +-968 -221 206 0 +-845 -515 746 0 +485 200 -915 0 +-801 835 78 0 +-360 517 -530 0 +-415 40 -545 0 +207 29 619 0 +363 -565 -557 0 +-32 346 24 0 +617 428 -446 0 +594 995 -564 0 +-123 -588 884 0 +-18 -801 -373 0 +-962 814 -526 0 +-289 605 -48 0 +222 -971 578 0 +-867 -551 -856 0 +-6 646 -445 0 +-485 -777 -480 0 +-573 -73 975 0 +-874 -126 -354 0 +-57 -559 501 0 +-188 -304 626 0 +-948 -474 383 0 +-496 -275 213 0 +616 606 -88 0 +228 612 240 0 +268 -482 -502 0 +-461 -403 -41 0 +-170 401 -841 0 +279 -579 435 0 +893 934 -311 0 +931 349 -484 0 +534 -247 308 0 +265 703 -585 0 +198 -570 166 0 +166 483 551 0 +-169 -542 -89 0 +-726 352 754 0 +-991 -951 -768 0 +-571 -133 -810 0 +-588 -976 -62 0 +-388 -840 935 0 +-211 799 -640 0 +-793 -63 -831 0 +682 180 637 0 +675 229 -364 0 +847 -572 -703 0 +800 -760 -56 0 +816 98 -78 0 +696 -679 547 0 +-715 987 -482 0 +-247 242 -972 0 +410 186 -174 0 +-194 61 -325 0 +859 787 836 0 +847 -39 -557 0 +-685 -148 -504 0 +-934 44 54 0 +904 -978 -186 0 +704 24 -276 0 +-59 113 -148 0 +384 491 -896 0 +-708 314 124 0 +220 -277 -229 0 +-74 -607 185 0 +211 -330 954 0 +427 201 562 0 +827 205 -253 0 +495 485 218 0 +-460 999 327 0 +-530 -958 -662 0 +-78 -234 -109 0 +185 -177 236 0 +675 893 -507 0 +-528 -915 510 0 +-972 111 -566 0 +915 -156 528 0 +901 -453 -489 0 +919 -91 -859 0 +-69 255 986 0 +-232 -33 286 0 +859 -99 -11 0 +-291 425 664 0 +-793 588 89 0 +615 -410 -521 0 +-953 -531 817 0 +537 168 -747 0 +808 123 -521 0 +-878 -978 779 0 +465 -986 -861 0 +295 872 -593 0 +190 159 147 0 +-441 -341 986 0 +144 -729 60 0 +559 877 -491 0 +29 -339 434 0 +-85 -297 140 0 +195 -6 115 0 +368 -609 -504 0 +-894 -749 623 0 +102 -366 743 0 +-823 -31 -567 0 +654 84 -148 0 +-130 116 -306 0 +728 -91 -281 0 +-628 -536 81 0 +269 901 920 0 +-695 -65 49 0 +-66 919 -884 0 +-508 88 -847 0 +-607 289 -682 0 +94 657 -131 0 +283 -508 841 0 +70 -479 -492 0 +227 574 -600 0 +690 708 515 0 +-853 -269 575 0 +-615 -717 18 0 +-139 166 -483 0 +720 746 976 0 +-328 320 -370 0 +985 709 637 0 +-499 -494 -589 0 +275 733 -469 0 +-666 877 -96 0 +644 362 653 0 +956 -27 -73 0 +-855 -834 -797 0 +-529 -922 -879 0 +-43 -573 404 0 +840 802 -831 0 +-42 -662 -303 0 +997 -340 -489 0 +-610 323 -901 0 +238 310 44 0 +-507 802 252 0 +839 84 870 0 +-676 -173 -606 0 +720 249 -358 0 +-796 422 139 0 +223 -946 246 0 +513 -700 -506 0 +560 -310 -147 0 +670 520 -652 0 +-146 -910 922 0 +333 -969 -164 0 +936 -814 585 0 +106 -135 979 0 +-48 191 544 0 +-667 -46 916 0 +551 -241 -269 0 +152 -493 231 0 +271 987 523 0 +-584 -751 444 0 +68 -488 661 0 +-490 -774 801 0 +-388 769 -394 0 +-319 -163 -936 0 +213 -978 410 0 +-856 339 -24 0 +590 -526 779 0 +753 -150 376 0 +866 253 -675 0 +-949 -892 -976 0 +260 -174 240 0 +339 351 -198 0 +-944 27 -773 0 +769 557 -149 0 +541 808 -100 0 +-847 601 -406 0 +-248 -786 546 0 +-596 -551 741 0 +537 -593 -253 0 +774 -333 -240 0 +-85 -244 696 0 +-190 -135 -392 0 +-916 141 721 0 +25 223 -354 0 +-966 -976 514 0 +572 -756 697 0 +370 98 -446 0 +585 -812 289 0 +775 -613 -943 0 +-171 -332 600 0 +-127 784 755 0 +-904 498 261 0 +-915 -462 961 0 +-733 -574 880 0 +-1000 -769 804 0 +-723 581 60 0 +-482 911 -884 0 +295 290 -271 0 +1 670 -304 0 +-13 452 772 0 +589 -963 -263 0 +781 132 87 0 +240 902 716 0 +464 636 564 0 +-853 179 297 0 +-359 -811 709 0 +-215 872 -534 0 +921 974 -653 0 +785 -964 -728 0 +108 741 307 0 +-890 21 -654 0 +-177 -236 686 0 +707 716 -998 0 +671 -791 936 0 +172 678 -967 0 +193 -742 800 0 +425 -880 780 0 +114 798 215 0 +964 954 -972 0 +-101 -320 -32 0 +583 812 -424 0 +973 607 -588 0 +-675 949 -544 0 +580 -790 -145 0 +-535 346 -911 0 +-334 388 -809 0 +-634 -25 -39 0 +-209 -148 520 0 +246 767 -669 0 +813 256 -148 0 +712 764 -19 0 +-755 -21 42 0 +-668 518 -187 0 +-711 954 -504 0 +768 753 -260 0 +-811 810 -824 0 +-225 941 -860 0 +751 -969 453 0 +-995 409 592 0 +-85 -582 791 0 +-681 -135 727 0 +-444 715 -286 0 +-303 199 373 0 +628 -966 -433 0 +-140 -186 967 0 +-930 758 850 0 +267 954 73 0 +-467 847 -272 0 +-466 -399 -104 0 +-906 459 -156 0 +465 -685 -412 0 +756 -482 795 0 +-661 -852 -464 0 +5 -615 116 0 +507 -752 607 0 +-184 298 -100 0 +305 104 424 0 +810 -771 -769 0 +-707 328 -936 0 +-506 -707 -899 0 +160 910 -833 0 +492 282 301 0 +633 211 -157 0 +256 231 -575 0 +-652 -794 881 0 +-874 963 880 0 +745 -136 -460 0 +-537 230 88 0 +-576 103 -42 0 +586 280 -862 0 +925 -5 863 0 +814 -567 72 0 +-852 -41 765 0 +410 419 -93 0 +985 654 -377 0 +-355 -171 750 0 +731 673 -576 0 +-240 633 -157 0 +578 959 936 0 +-981 675 -205 0 +690 -393 452 0 +603 -909 251 0 +222 -875 -689 0 +-597 -837 -124 0 +859 -345 -683 0 +123 -938 -452 0 +905 375 -465 0 +-947 -927 672 0 +369 33 -648 0 +-861 -530 -346 0 +740 290 845 0 +-94 559 589 0 +-753 301 -57 0 +-70 -486 -537 0 +-913 -607 -76 0 +703 -826 -202 0 +-192 303 -663 0 +-749 194 274 0 +889 -733 89 0 +-978 551 999 0 +344 -655 251 0 +-288 718 -470 0 +-411 687 36 0 +864 -890 252 0 +497 -431 -15 0 +-620 79 -411 0 +-972 -337 -712 0 +-645 923 -372 0 +-878 -545 747 0 +683 -211 -38 0 +-437 764 -30 0 +413 -40 -740 0 +-526 -392 -574 0 +-330 982 323 0 +649 587 200 0 +232 -586 -256 0 +-324 215 -510 0 +7 249 83 0 +933 767 252 0 +-481 670 -457 0 +-894 322 68 0 +473 -832 552 0 +555 -295 100 0 +-684 946 397 0 +383 417 381 0 +-755 759 634 0 +5 674 -708 0 +154 684 -647 0 +-501 -219 844 0 +-944 154 -949 0 +-353 411 633 0 +561 573 -430 0 +445 -773 -111 0 +445 436 -786 0 +-617 385 -609 0 +50 820 -763 0 +797 -553 -104 0 +719 -557 900 0 +-896 299 -738 0 +-751 232 947 0 +181 -189 -607 0 +768 293 -818 0 +955 -35 -687 0 +28 298 310 0 +688 -761 -269 0 +-937 459 -143 0 +834 807 -11 0 +-601 61 300 0 +-642 -137 -562 0 +-653 -78 536 0 +423 -435 -68 0 +-205 -367 623 0 +-615 -260 266 0 +-280 -685 955 0 +-341 539 504 0 +137 850 538 0 +767 -488 670 0 +-454 -607 457 0 +-75 107 928 0 +-4 324 -894 0 +-817 -272 113 0 +-673 -186 149 0 +-732 -393 -472 0 +865 -102 -551 0 +345 -404 -846 0 +-427 -468 -857 0 +188 466 -698 0 +805 -470 939 0 +-559 -565 42 0 +466 -208 756 0 +795 465 -367 0 +495 -787 -281 0 +-126 921 -222 0 +271 -980 192 0 +823 -767 974 0 +577 827 -822 0 +716 -614 694 0 +472 774 883 0 +-653 -74 -847 0 +376 -448 382 0 +369 689 973 0 +416 880 -869 0 +937 810 -967 0 +677 560 -627 0 +717 994 173 0 +-784 -392 -422 0 +-965 6 -545 0 +-870 1000 296 0 +950 -356 -171 0 +674 380 48 0 +-953 276 377 0 +984 -642 24 0 +-225 968 -25 0 +6 -995 99 0 +-861 686 -907 0 +578 19 74 0 +-307 474 -768 0 +74 109 -774 0 +900 -545 129 0 +754 -403 609 0 +966 -327 -186 0 +314 310 -382 0 +632 622 -227 0 +999 -254 -470 0 +561 481 -768 0 +350 -108 603 0 +-248 742 -527 0 +-368 131 837 0 +-633 479 19 0 +-597 -32 166 0 +-384 349 -253 0 +-211 618 -734 0 +319 591 997 0 +211 60 -687 0 +293 -689 475 0 +-18 -636 -315 0 +-880 -109 -332 0 +256 -172 -82 0 +-591 -788 371 0 +-997 689 960 0 +-624 -428 936 0 +665 181 -385 0 +1 -898 -886 0 +-377 -577 379 0 +-729 235 954 0 +921 173 -635 0 +904 -544 -112 0 +-919 660 875 0 +-548 180 -442 0 +598 -386 -331 0 +176 -843 -339 0 +943 -944 -273 0 +431 -671 -948 0 +-97 841 -688 0 +-10 78 600 0 +714 -595 867 0 +592 -431 -990 0 +-110 672 -765 0 +-70 -33 -508 0 +733 -730 661 0 +-585 -861 763 0 +-363 319 -553 0 +252 -536 209 0 +-656 641 412 0 +453 773 -200 0 +647 541 24 0 +-784 -536 -948 0 +-247 381 -260 0 +800 -626 -405 0 +-204 -1000 639 0 +-241 -799 -536 0 +387 223 2 0 +-930 -129 -441 0 +116 -829 -637 0 +668 -975 977 0 +-636 387 -948 0 +741 188 -410 0 +-106 934 -17 0 +240 675 629 0 +970 68 332 0 +627 -6 -591 0 +374 68 399 0 +-357 853 373 0 +-616 -114 358 0 +701 78 910 0 +-121 679 115 0 +594 -640 81 0 +68 871 981 0 +-34 -765 -800 0 +-503 -582 651 0 +922 -839 -501 0 +-236 757 661 0 +-3 -883 640 0 +174 389 -61 0 +-1 -110 -705 0 +-246 663 -25 0 +485 -968 -47 0 +413 794 80 0 +-339 60 -379 0 +-760 942 -748 0 +782 744 -414 0 +409 747 -691 0 +126 411 -619 0 +-715 -431 -597 0 +-922 -147 -145 0 +-826 252 -996 0 +-651 -296 263 0 +-796 291 882 0 +-790 472 -61 0 +412 -31 -59 0 +523 611 -211 0 +942 -917 -613 0 +-613 -147 -587 0 +-481 -359 -822 0 +769 -26 854 0 +504 -566 -930 0 +728 -211 -559 0 +-331 -84 9 0 +456 872 -158 0 +774 668 272 0 +107 -142 786 0 +85 217 -278 0 +-460 -282 -945 0 +751 -46 -981 0 +-729 522 -433 0 +496 -177 -85 0 +541 -430 -543 0 +987 364 -929 0 +-417 -124 -659 0 +935 13 302 0 +65 -707 117 0 +401 -112 -351 0 +-610 940 366 0 +302 544 -928 0 +898 -417 732 0 +-966 391 124 0 +24 -114 -470 0 +374 -799 741 0 +-160 915 423 0 +-26 -124 132 0 +-239 408 161 0 +-350 88 -389 0 +602 466 261 0 +471 -180 505 0 +881 178 -345 0 +-474 811 77 0 +-366 -62 565 0 +-113 -43 519 0 +-688 380 -435 0 +227 -439 -73 0 +-293 -774 -343 0 +-354 -781 143 0 +-211 510 859 0 +-55 80 -499 0 +-738 -522 -849 0 +-964 -206 761 0 +126 39 -906 0 +863 759 -292 0 +30 -449 995 0 +-768 860 175 0 +-658 -86 -26 0 +762 532 -639 0 +-216 386 554 0 +-443 306 -756 0 +754 747 838 0 +569 -115 340 0 +925 -725 971 0 +-645 665 -603 0 +-421 687 -982 0 +797 508 -485 0 +84 207 -828 0 +409 -943 -432 0 +-920 30 -226 0 +-630 -939 -127 0 +-246 340 -711 0 +-948 366 200 0 +-542 -828 441 0 +-513 -759 78 0 +404 289 -81 0 +-868 -88 803 0 +4 376 -888 0 +273 -31 596 0 +-760 -468 168 0 +-783 98 431 0 +933 159 705 0 +560 334 -437 0 +-60 418 875 0 +-641 267 -419 0 +-456 -280 -201 0 +-229 205 587 0 +695 644 93 0 +-467 14 -714 0 +704 805 883 0 +-113 498 -355 0 +-703 12 -262 0 +-242 -604 -649 0 +702 251 -244 0 +518 640 328 0 +398 -137 476 0 +-374 -504 -709 0 +-898 -186 289 0 +39 752 147 0 +685 53 601 0 +-73 -547 881 0 +-662 808 -52 0 +-232 -493 278 0 +-146 649 -461 0 +-226 776 931 0 +-881 -463 206 0 +728 605 -331 0 +-9 -600 619 0 +815 -592 -730 0 +930 -693 -877 0 +-314 -961 807 0 +-398 316 -733 0 +-897 -81 -539 0 +254 -948 -383 0 +170 -379 -793 0 +183 624 -652 0 +937 686 98 0 +-106 -976 330 0 +-602 1 -127 0 +-22 271 751 0 +87 -466 515 0 +-665 -216 238 0 +970 -802 576 0 +-418 243 968 0 +4 -622 -510 0 +954 -44 -547 0 +-681 -552 579 0 +-495 -525 6 0 +-546 -466 860 0 +883 722 115 0 +-914 558 575 0 +-255 -156 647 0 +-640 -228 -114 0 +747 352 297 0 +354 -627 179 0 +-44 -908 850 0 +-745 838 -243 0 +676 998 893 0 +748 -514 98 0 +-890 -175 -589 0 +111 -873 7 0 +124 803 748 0 +48 -711 139 0 +-641 576 233 0 +-553 163 598 0 +327 -192 -299 0 +-588 -306 796 0 +-341 -926 688 0 +73 -569 -955 0 +320 -958 74 0 +411 2 -210 0 +159 582 -51 0 +-510 163 -378 0 +-935 42 -513 0 +-973 -651 952 0 +-886 -276 884 0 +-343 -295 434 0 +-66 521 -888 0 +90 -599 -176 0 +797 257 68 0 +938 -108 -129 0 +-476 282 231 0 +887 273 -480 0 +-437 674 162 0 +735 911 -334 0 +-543 -316 -422 0 +747 335 39 0 +-599 -236 567 0 +692 499 -589 0 +780 -393 970 0 +879 -318 -633 0 +756 446 541 0 +-84 -770 -606 0 +954 266 934 0 +-316 243 -584 0 +-359 311 817 0 +-807 648 -685 0 +-1 -224 915 0 +-485 -309 346 0 +-961 110 122 0 +371 173 147 0 +-956 -757 -321 0 +749 104 -467 0 +-344 709 765 0 +-521 -278 -297 0 +635 -354 183 0 +678 920 -955 0 +82 -883 -672 0 +643 -38 274 0 +15 -871 -427 0 +-276 607 357 0 +477 -728 394 0 +-910 -84 163 0 +136 908 758 0 +-934 -493 533 0 +70 -290 424 0 +740 -4 960 0 +178 -775 -770 0 +135 598 62 0 +319 38 955 0 +-566 -907 -781 0 +569 99 470 0 +15 -610 977 0 +538 221 119 0 +-227 -477 860 0 +-479 136 -786 0 +305 564 -772 0 +504 -593 63 0 +66 -34 601 0 +423 -576 -305 0 +64 -265 -969 0 +-118 143 369 0 +-486 824 -261 0 +-39 -363 -809 0 +996 -197 -297 0 +-328 -401 -782 0 +-28 -581 806 0 +-397 -474 953 0 +-45 -661 172 0 +870 -213 683 0 +298 -69 492 0 +838 511 -360 0 +-400 514 195 0 +782 884 638 0 +-421 -192 -789 0 +-277 -472 -384 0 +-191 -579 73 0 +-944 -585 -897 0 +1 301 143 0 +404 -815 -342 0 +-136 -857 -183 0 +576 22 -773 0 +-877 548 654 0 +578 -600 93 0 +513 -128 353 0 +688 -325 -652 0 +-631 512 71 0 +74 -15 -638 0 +748 -597 356 0 +-344 366 -575 0 +-153 -835 -117 0 +-274 -332 -997 0 +-835 333 -36 0 +-217 -320 40 0 +-91 240 435 0 +-796 -311 851 0 +506 538 -915 0 +150 -318 -895 0 +-251 -818 631 0 +552 628 63 0 +713 -447 -535 0 +184 -786 386 0 +-458 -422 573 0 +327 191 5 0 +289 291 220 0 +62 222 -208 0 +-463 -970 -52 0 +336 727 612 0 +-753 -464 -596 0 +379 -948 321 0 +593 -880 -698 0 +-366 331 -328 0 +-351 -235 193 0 +871 671 -663 0 +-544 479 147 0 +323 406 -21 0 +172 46 262 0 +-500 -138 715 0 +966 776 491 0 +149 6 338 0 +-477 500 -650 0 +-243 850 580 0 +-768 -76 -232 0 +376 -438 912 0 +310 -674 -3 0 +940 -474 -645 0 +46 -866 142 0 +373 969 -495 0 +-358 801 -758 0 +736 -496 -20 0 +-580 1 479 0 +133 658 -577 0 +899 -580 -558 0 +607 -427 850 0 +991 82 764 0 +14 -514 -434 0 +848 -553 -385 0 +73 791 -509 0 +-277 23 799 0 +821 -961 538 0 +676 -5 706 0 +-864 -257 -941 0 +-124 32 -150 0 +-490 576 -171 0 +-44 -835 -257 0 +-715 -706 341 0 +992 -752 -70 0 +56 -435 -217 0 +348 298 -680 0 +604 325 -30 0 +-529 -881 564 0 +-971 -548 -233 0 +800 -382 -224 0 +343 -173 -587 0 +-189 -368 -319 0 +-901 975 -494 0 +728 627 768 0 +533 224 941 0 +738 240 -871 0 +473 589 -39 0 +-569 -185 706 0 +-817 342 358 0 +145 -956 -549 0 +306 -69 -485 0 +550 842 929 0 +-698 113 -9 0 +-143 -884 -488 0 +-891 -474 -907 0 +-62 -451 793 0 +-836 730 896 0 +382 -755 936 0 +83 366 712 0 +-765 874 -679 0 +840 -541 -382 0 +-784 297 -334 0 +-444 -144 -705 0 +-372 -821 -798 0 +102 -292 577 0 +524 -49 225 0 +-699 -225 420 0 +780 -221 807 0 +832 959 -951 0 +-443 146 -998 0 +-336 312 -425 0 +-724 -2 -490 0 +488 -472 632 0 +606 997 -474 0 +989 -725 163 0 +-30 -484 365 0 +914 -465 908 0 +-896 378 -151 0 +-901 599 23 0 +193 -643 915 0 +738 168 322 0 +-599 -231 -477 0 +599 -163 985 0 +-645 829 713 0 +-751 596 80 0 +147 -171 69 0 +990 737 -961 0 +84 111 951 0 +944 -679 -910 0 +245 371 -771 0 +-337 62 -461 0 +272 -47 -326 0 +418 189 927 0 +867 810 -657 0 +835 856 -649 0 +-628 -360 658 0 +-139 -351 490 0 +177 -373 287 0 +847 -448 98 0 +-108 488 544 0 +-23 578 476 0 +178 -683 611 0 +-656 -309 285 0 +938 -913 632 0 +606 700 -649 0 +27 421 -624 0 +201 -587 822 0 +697 111 -844 0 +-276 -355 -736 0 +953 278 -606 0 +518 609 173 0 +-795 -86 35 0 +212 -146 398 0 +-811 375 -854 0 +-770 807 346 0 +435 983 -403 0 +73 300 94 0 +940 -879 134 0 +78 -307 136 0 +-507 110 -600 0 +655 -264 987 0 +265 150 -29 0 +348 724 -635 0 +238 339 343 0 +-591 91 -949 0 +186 -313 -771 0 +-571 825 -160 0 +-363 -721 -627 0 +-488 726 16 0 +482 -958 976 0 +-407 150 963 0 +835 76 884 0 +456 -354 241 0 +-46 458 561 0 +-772 426 -802 0 +-814 110 -232 0 +8 708 794 0 +-341 -581 66 0 +385 946 77 0 +-294 628 -495 0 +439 131 -593 0 +379 570 -337 0 +-967 -353 137 0 +693 -923 -958 0 +-475 -278 274 0 +856 -308 -527 0 +-204 918 -326 0 +503 328 859 0 +679 -667 -502 0 +-521 415 -495 0 +-968 299 -45 0 +-80 699 349 0 +359 -621 -602 0 +962 136 -982 0 +-868 15 758 0 +-742 -91 -717 0 +-469 733 436 0 +-308 -672 79 0 +-815 605 379 0 +-687 -600 -855 0 +658 -634 517 0 +-419 -624 -216 0 +520 620 -297 0 +502 664 -672 0 +174 -194 -347 0 +642 285 409 0 +-626 856 698 0 +-819 -994 431 0 +624 -349 -308 0 +350 -876 540 0 +126 424 -893 0 +-560 -376 -543 0 +-97 -390 -875 0 +439 -925 -413 0 +-357 -516 832 0 +599 -609 -768 0 +-698 -340 -765 0 +108 421 -964 0 +-856 -7 964 0 +65 -504 -85 0 +694 -57 -224 0 +73 -62 -288 0 +326 946 785 0 +36 853 169 0 +-574 156 538 0 +127 -374 -935 0 +375 -5 -761 0 +817 583 -403 0 +-178 -316 -825 0 +-193 -751 293 0 +526 -522 848 0 +91 -354 -53 0 +363 -168 680 0 +-721 -229 -418 0 +-927 -319 -653 0 +-410 -710 546 0 +391 644 967 0 +-636 -50 225 0 +-445 -635 631 0 +-26 701 340 0 +83 -96 868 0 +-607 -522 865 0 +-620 -519 62 0 +-199 750 -54 0 +959 -533 -492 0 +51 665 -784 0 +209 -654 137 0 +574 -262 622 0 +-41 -567 -415 0 +319 708 -563 0 +-441 -146 -569 0 +-166 354 -661 0 +606 -382 -255 0 +756 -122 109 0 +-354 -577 399 0 +-225 212 -289 0 +761 951 703 0 +-132 828 -690 0 +-389 501 -185 0 +-573 -462 78 0 +272 511 -42 0 +810 358 467 0 +-389 -286 678 0 +-44 -391 -415 0 +987 825 807 0 +73 204 -589 0 +532 937 -434 0 +637 797 410 0 +-227 -840 -889 0 +760 437 839 0 +644 -221 325 0 +-790 -670 -961 0 +-353 -999 445 0 +-625 -135 -52 0 +416 -709 -393 0 +-642 545 -875 0 +-49 -303 297 0 +201 -597 204 0 +420 -150 995 0 +-265 -519 -853 0 +-889 401 737 0 +779 679 186 0 +583 88 -299 0 +561 252 958 0 +884 -23 570 0 +210 -20 266 0 +706 263 -912 0 +-937 648 -521 0 +-601 -176 672 0 +-455 -640 138 0 +-904 -721 -259 0 +-70 -612 872 0 +-678 635 215 0 +-768 526 707 0 +-690 -494 -752 0 +360 625 572 0 +154 -66 512 0 +929 738 -286 0 +963 698 177 0 +449 -713 -212 0 +-292 -539 551 0 +-841 -688 -122 0 +452 817 -256 0 +-426 -312 -263 0 +-463 407 561 0 +-968 373 147 0 +765 -359 303 0 +420 -51 -862 0 +-815 676 237 0 +572 470 -540 0 +-927 -889 -547 0 +-111 -116 649 0 +-981 -546 463 0 +-513 -146 400 0 +708 -102 461 0 +-140 1000 789 0 +-724 615 576 0 +635 -197 -291 0 +263 658 590 0 +182 -966 -289 0 +-865 -74 -447 0 +705 327 -531 0 +954 540 -56 0 +-839 38 -857 0 +-218 -691 736 0 +-660 639 816 0 +-63 -637 519 0 +-49 -819 -336 0 +989 -803 -838 0 +-365 -438 -203 0 +24 -494 -430 0 +791 -550 493 0 +-666 -793 100 0 +-725 -139 -253 0 +-787 -9 -191 0 +-208 -322 -895 0 +997 -371 491 0 +-443 599 -220 0 +-386 -969 -731 0 +261 -648 878 0 +834 -158 730 0 +998 392 276 0 +-939 472 -427 0 +-310 -797 618 0 +881 -785 485 0 +-95 -854 382 0 +541 956 -737 0 +-826 983 -163 0 +-232 -310 306 0 +-149 -355 -706 0 +884 -86 475 0 +-126 782 -631 0 +952 -730 934 0 +-760 -1000 971 0 +-710 125 472 0 +650 948 -457 0 +830 94 -201 0 +429 772 839 0 +-401 953 -25 0 +-402 847 -905 0 +407 -420 235 0 +239 705 519 0 +339 -963 545 0 +-811 -300 -151 0 +163 -913 -107 0 +-46 248 726 0 +982 630 -612 0 +577 381 417 0 +-686 -780 -642 0 +-395 -28 -330 0 +-67 986 -427 0 +717 999 -363 0 +-174 -878 843 0 +376 829 795 0 +779 -322 129 0 +-42 70 752 0 +-33 850 358 0 +690 -527 -923 0 +-761 867 328 0 +-927 117 554 0 +159 -997 -427 0 +316 509 854 0 +373 124 -442 0 +-856 852 -708 0 +638 -720 899 0 +-434 861 -912 0 +824 -402 -795 0 +817 215 704 0 +441 13 439 0 +83 687 -714 0 +-791 -70 69 0 +412 -728 931 0 +-240 122 -961 0 +378 220 450 0 +493 612 228 0 +-189 521 912 0 +-772 536 -436 0 +-380 -578 -859 0 +905 305 -489 0 +430 48 -1000 0 +920 294 -312 0 +-670 -797 47 0 +-423 -86 -169 0 +958 -531 817 0 +-163 -743 -855 0 +-225 956 -769 0 +-852 912 282 0 +952 -276 -978 0 +173 -618 706 0 +769 -823 555 0 +375 -740 577 0 +889 -306 585 0 +-415 258 -163 0 +-121 337 -428 0 +-745 -16 259 0 +192 556 -850 0 +772 617 -606 0 +-598 -260 -180 0 +741 -108 -988 0 +-363 3 967 0 +-590 -941 587 0 +506 -391 817 0 +-102 183 -368 0 +-341 -790 -772 0 +-965 -65 902 0 +245 429 -940 0 +613 365 186 0 +-933 718 -175 0 +615 636 -111 0 +-763 -138 -578 0 +903 -851 -319 0 +196 -702 -289 0 +787 -988 455 0 +688 426 603 0 +206 46 -204 0 +-530 -986 994 0 +979 875 -79 0 +-603 557 -25 0 +62 -358 -811 0 +-231 -96 -457 0 +-72 599 779 0 +300 489 -200 0 +-804 936 433 0 +923 738 -565 0 +919 -879 -563 0 +269 -967 -747 0 +-318 669 -546 0 +-226 173 369 0 +-844 -550 433 0 +809 -514 -354 0 +-911 -932 -844 0 +814 -481 -628 0 +813 497 -61 0 +650 326 -206 0 +478 506 -382 0 +-908 -341 457 0 +-713 -411 140 0 +-384 -276 -805 0 +689 232 -860 0 +727 -337 273 0 +121 534 25 0 +384 -403 -338 0 +-128 299 -615 0 +-363 -714 612 0 +63 -17 767 0 +-522 685 32 0 +-921 -256 -427 0 +393 -748 413 0 +17 -55 -792 0 +-483 559 116 0 +634 -489 453 0 +-458 5 968 0 +-94 246 946 0 +-919 -678 -509 0 +340 -181 513 0 +-668 234 570 0 +-913 521 -393 0 +831 -534 973 0 +928 202 -522 0 +-740 -429 535 0 +-454 118 -895 0 +-91 -402 993 0 +-806 763 994 0 +573 710 -133 0 +258 -455 -9 0 +-481 897 287 0 +692 -650 378 0 +6 103 -151 0 +4 -176 -80 0 +111 -787 -248 0 +-946 782 -954 0 +917 772 165 0 +308 833 224 0 +-439 -156 791 0 +284 -613 912 0 +832 443 -240 0 +945 859 171 0 +284 -326 590 0 +-21 76 193 0 +-659 -315 942 0 +-121 -923 502 0 +-913 328 -578 0 +-149 563 561 0 +-299 -866 -673 0 +-44 528 -576 0 +-385 545 -813 0 +-249 625 694 0 +909 -328 571 0 +-240 237 -86 0 +-624 -164 -449 0 +-687 -494 -319 0 +209 -664 950 0 +997 828 972 0 +-350 -213 -488 0 +-15 -558 85 0 +-717 842 532 0 +-944 -265 -932 0 +-123 -880 211 0 +-530 -857 702 0 +373 548 -883 0 +-773 -930 992 0 +809 -788 -786 0 +996 911 454 0 +129 525 265 0 +-101 -983 -856 0 +550 -806 286 0 +417 -828 -999 0 +551 70 -194 0 +12 -896 191 0 +-935 882 -963 0 +986 -487 -733 0 +319 -1000 -384 0 +140 -920 -703 0 +-347 -10 594 0 +482 -645 906 0 +-982 951 295 0 +926 -499 846 0 +732 -215 -797 0 +923 81 752 0 +-696 791 -978 0 +-130 -636 -666 0 +-298 46 142 0 +-946 -318 -332 0 +520 753 402 0 +242 745 796 0 +-124 878 631 0 +366 312 840 0 +-76 -254 -113 0 +-680 808 565 0 +-721 223 339 0 +939 868 -149 0 +964 31 644 0 +-340 768 -291 0 +246 366 -473 0 +804 182 283 0 +348 56 941 0 +-239 71 104 0 +-365 443 -959 0 +-924 -314 986 0 +-939 -157 -148 0 +48 -344 421 0 +-133 -914 -356 0 +706 -302 200 0 +-261 599 -761 0 +-606 -111 -207 0 +232 661 113 0 +-995 -997 180 0 +179 353 450 0 +39 -343 -540 0 +949 -360 -824 0 +149 -588 -961 0 +-620 -739 -915 0 +376 -801 -152 0 +-301 -278 300 0 +778 -966 -504 0 +947 -915 -325 0 +293 -453 280 0 +-184 -94 507 0 +-920 -360 73 0 +-500 -578 589 0 +-257 -315 835 0 +-396 -501 618 0 +-217 -692 -232 0 +-305 741 522 0 +611 635 -340 0 +336 -199 -739 0 +-61 -218 243 0 +-419 -745 723 0 +-68 846 -67 0 +222 -634 -479 0 +-220 -483 -586 0 +964 -126 368 0 +-927 297 -964 0 +-843 955 708 0 +-100 -895 -734 0 +271 -62 -404 0 +346 111 65 0 +419 -192 781 0 +-952 -404 209 0 +-850 -18 -277 0 +164 -419 671 0 +958 -292 800 0 +636 289 362 0 +-122 -28 837 0 +480 396 954 0 +-888 -508 381 0 +-910 -715 559 0 +-422 104 -331 0 +-736 586 679 0 +-362 733 -34 0 +-330 953 967 0 +127 -215 296 0 +-415 675 -809 0 +-606 753 -599 0 +156 946 70 0 +-355 -73 396 0 +-32 -99 177 0 +100 862 729 0 +-648 -45 125 0 +675 -543 -80 0 +396 669 -338 0 +-370 -607 -89 0 +792 106 -925 0 +352 -396 -430 0 +-129 957 -290 0 +358 -218 54 0 +-917 -995 -668 0 +-221 -140 -347 0 +-334 -722 890 0 +-458 -893 230 0 +-209 987 -175 0 +928 -993 -96 0 +-208 976 -410 0 +576 966 252 0 +-157 460 -914 0 +306 -965 -122 0 +463 -425 -954 0 +105 557 243 0 +270 -914 -517 0 +-352 -579 979 0 +35 -679 -855 0 +-610 51 154 0 +546 -137 -612 0 +396 913 -605 0 +-489 -262 535 0 +51 -959 209 0 +-719 292 764 0 +-759 566 365 0 +-401 331 -118 0 +237 -622 -192 0 +790 447 987 0 +842 -290 857 0 +267 -970 -207 0 +830 -688 215 0 +549 -540 402 0 +-303 -427 446 0 +-987 -655 176 0 +521 -709 806 0 +-602 -805 -178 0 +-743 960 -580 0 +-524 -29 -353 0 +-187 -190 663 0 +-485 -180 5 0 +-380 -1 -871 0 +-186 -405 92 0 +242 -736 832 0 +860 915 -598 0 +64 62 -667 0 +-292 47 -409 0 +362 612 -935 0 +69 -448 882 0 +-291 784 -539 0 +979 -641 407 0 +97 342 769 0 +-366 38 174 0 +-596 -509 777 0 +130 892 261 0 +314 75 -524 0 +256 795 510 0 +380 864 771 0 +-672 -361 -477 0 +776 -219 595 0 +-861 898 234 0 +-371 -187 300 0 +635 -76 156 0 +828 518 490 0 +825 846 -614 0 +453 6 482 0 +-334 -33 -309 0 +-28 546 -757 0 +485 -274 95 0 +-363 -548 877 0 +879 -82 -689 0 +-723 100 674 0 +418 76 -706 0 +908 9 962 0 +-23 510 843 0 +-193 860 171 0 +935 -4 127 0 +350 103 131 0 +464 -459 -515 0 +51 776 734 0 +-448 -342 642 0 +614 -24 694 0 +-51 -721 -994 0 +538 -600 -611 0 +916 88 -287 0 +-488 -939 153 0 +252 677 746 0 +263 71 616 0 +934 -920 -10 0 +605 -252 925 0 +-680 496 -880 0 +648 -640 -4 0 +567 100 -831 0 +196 -712 388 0 +-488 -18 497 0 +886 -267 -637 0 +-504 519 111 0 +-96 277 697 0 +146 -48 453 0 +-305 815 330 0 +-921 -142 715 0 +-110 -43 -948 0 +612 -922 13 0 +799 659 309 0 +-315 369 54 0 +-831 338 352 0 +-515 880 100 0 +-575 -675 -470 0 +-236 -283 -76 0 +-125 -112 -130 0 +431 935 116 0 +-34 953 451 0 +629 -713 640 0 +-96 379 -681 0 +200 402 99 0 +-953 -423 -386 0 +-166 637 -113 0 +563 314 -179 0 +877 264 -993 0 +-337 48 -743 0 +-362 -390 844 0 +-542 -374 -376 0 +305 -468 -939 0 +-801 541 726 0 +-239 802 716 0 +-381 418 -676 0 +593 -656 241 0 +418 -757 125 0 +-823 -485 -303 0 +-459 -747 -345 0 +846 -209 -709 0 +-739 565 655 0 +-945 484 -56 0 +-373 -659 211 0 +-165 -624 -153 0 +395 446 -267 0 +189 -32 137 0 +368 -597 -679 0 +415 270 -503 0 +37 -903 -68 0 +30 753 -203 0 +-760 -520 777 0 +728 196 445 0 +-180 695 823 0 +152 -284 140 0 +-898 409 -862 0 +849 69 -839 0 +225 694 -575 0 +210 45 -18 0 +-691 -297 76 0 +195 -820 -485 0 +-27 -741 -956 0 +-81 -514 -825 0 +831 -72 268 0 +-258 -723 -984 0 +476 351 414 0 +101 76 722 0 +-291 -866 -567 0 +411 268 98 0 +-988 599 -418 0 +991 366 -270 0 +141 478 -744 0 +-787 497 756 0 +535 -388 219 0 +-817 -815 250 0 +-690 544 -749 0 +-937 20 -404 0 +46 693 82 0 +584 -897 -847 0 +939 653 -335 0 +-189 -903 -400 0 +844 519 -652 0 +135 -257 491 0 +52 -312 103 0 +-642 -625 -800 0 +-724 -850 -785 0 +-547 279 -986 0 +-632 -600 -108 0 +62 -735 -204 0 +82 213 -231 0 +364 308 277 0 +-325 -534 504 0 +-755 872 760 0 +910 423 -639 0 +-702 854 -156 0 +213 655 232 0 +753 729 550 0 +-282 -98 232 0 +987 -999 5 0 +784 54 481 0 +947 844 599 0 +-112 1000 295 0 +-663 -235 190 0 +-354 700 -746 0 +233 245 517 0 +596 -415 987 0 +-117 -458 877 0 +228 788 703 0 +285 -9 661 0 +-370 -407 -539 0 +407 -324 92 0 +695 -246 260 0 +-573 -165 -544 0 +35 85 -240 0 +-549 -441 496 0 +-891 631 703 0 +-389 -548 368 0 +-385 -457 807 0 +-650 -691 708 0 +-877 -153 -832 0 +-209 958 292 0 +643 -153 -640 0 +710 45 300 0 +-603 171 -901 0 +401 -984 751 0 +540 372 724 0 +601 995 231 0 +605 -861 211 0 +-61 -89 660 0 +232 411 31 0 +-207 471 632 0 +-886 7 436 0 +248 -137 464 0 +616 -754 29 0 +-684 -645 807 0 +532 -668 -194 0 +477 -541 227 0 +-793 -670 -775 0 +-323 -675 637 0 +325 508 -612 0 +499 -71 -335 0 +482 67 677 0 +-87 905 492 0 +-616 -328 -228 0 +304 964 -228 0 +-308 -359 952 0 +845 -652 794 0 +161 -92 375 0 +670 -872 926 0 +686 6 -576 0 +-732 33 -630 0 +-151 -341 400 0 +937 -890 160 0 +-92 -971 -730 0 +207 -232 107 0 +-810 -597 -213 0 +312 246 -944 0 +503 -504 -473 0 +-448 654 -243 0 +267 367 819 0 +-441 765 270 0 +-582 -189 713 0 +-763 762 419 0 +530 678 -442 0 +-482 599 -495 0 +-469 -535 555 0 +-209 856 -11 0 +-370 569 -165 0 +9 307 654 0 +175 -718 51 0 +530 736 205 0 +-635 972 -848 0 +746 -419 -427 0 +571 -84 181 0 +-248 414 -298 0 +-240 293 664 0 +-196 657 -8 0 +328 -629 623 0 +777 -690 196 0 +155 -330 117 0 +-37 891 -40 0 +-630 222 -926 0 +-389 296 -48 0 +359 666 455 0 +-20 636 300 0 +-122 374 -427 0 +-918 90 -107 0 +217 958 984 0 +973 -656 -134 0 +-753 288 715 0 +206 903 435 0 +874 118 -447 0 +-882 146 -105 0 +-760 -635 -580 0 +-712 -733 140 0 +-50 919 788 0 +87 791 -16 0 +213 506 -42 0 +395 171 -898 0 +687 -829 -91 0 +-325 819 553 0 +-449 169 643 0 +799 -734 -270 0 +324 -305 372 0 +-757 -114 17 0 +71 -969 275 0 +490 544 136 0 +16 -774 745 0 +-578 -736 487 0 +210 -812 428 0 +-255 -412 -159 0 +114 -583 208 0 +778 290 985 0 +171 -466 -797 0 +-35 -254 124 0 +643 979 524 0 +-405 -922 979 0 +177 990 -54 0 +456 -733 371 0 +-369 280 786 0 +527 986 658 0 +173 -291 -613 0 +-176 471 726 0 +234 908 -576 0 +-597 -760 -33 0 +410 340 93 0 +898 457 622 0 +-158 -671 -308 0 +-786 714 -543 0 +-400 846 -507 0 +59 -497 74 0 +912 915 819 0 +464 -798 -938 0 +589 -222 -143 0 +-830 207 731 0 +-285 -472 -748 0 +88 65 125 0 +-948 -11 366 0 +-452 161 420 0 +-395 984 818 0 +619 -508 -358 0 +-644 -49 -923 0 +-273 580 176 0 +-463 540 -724 0 +-666 -337 340 0 +118 161 -282 0 +-506 796 -387 0 +-754 610 190 0 +-434 152 -468 0 +-329 -991 -760 0 +-682 324 -438 0 +-601 -3 -127 0 +-5 -453 254 0 +516 -597 -925 0 +-239 641 -486 0 +-14 795 -113 0 +-251 -145 -810 0 +817 426 854 0 +111 997 -370 0 +-243 -147 965 0 +106 -911 9 0 +-606 -628 623 0 +-6 -259 122 0 +105 -958 658 0 +932 416 24 0 +-158 -56 322 0 +968 -651 -185 0 +-186 -671 346 0 +749 911 717 0 +-816 -912 653 0 +38 221 663 0 +-379 59 313 0 +-164 -414 -295 0 +-34 638 -633 0 +-794 490 457 0 +102 -582 -728 0 +-490 -161 -927 0 +902 677 -322 0 +221 922 746 0 +-869 350 -304 0 +184 145 734 0 +641 192 624 0 +-305 -492 -430 0 +611 786 -841 0 +-13 -949 764 0 +-500 364 -783 0 +277 -155 736 0 +890 -48 603 0 +506 -371 504 0 +456 -452 371 0 +513 -427 -584 0 +198 -820 433 0 +809 -206 -373 0 +710 -731 505 0 +-120 481 656 0 +458 -999 -600 0 +347 610 -56 0 +-361 -753 139 0 +426 -982 641 0 +-820 802 -961 0 +957 701 340 0 +-84 -643 30 0 +963 -464 919 0 +301 -643 472 0 +-354 42 -297 0 +-705 -650 694 0 +-818 714 206 0 +-289 -397 -274 0 +70 711 -516 0 +538 739 -683 0 +-328 159 658 0 +979 12 80 0 +-702 -899 173 0 +-691 746 685 0 +649 720 -628 0 +329 -231 871 0 +884 -361 69 0 +-939 -112 -245 0 +-569 174 -214 0 +-792 833 -579 0 +-521 570 -469 0 +-761 510 808 0 +-32 -901 -894 0 +756 204 293 0 +-202 290 102 0 +-697 -638 -343 0 +874 -533 934 0 +576 -99 965 0 +419 206 -92 0 +111 -777 -827 0 +-936 323 716 0 +-155 -584 291 0 +46 -164 -438 0 +559 759 722 0 +628 -821 -569 0 +-360 -876 555 0 +279 -732 -432 0 +824 -579 348 0 +-363 -283 945 0 +101 423 -56 0 +588 855 -684 0 +757 257 214 0 +-488 29 -775 0 +316 -14 -667 0 +742 -832 954 0 +-591 -694 -859 0 +-147 986 -798 0 +640 -662 437 0 +-828 -462 871 0 +-991 430 153 0 +-719 -303 6 0 +343 73 495 0 +465 592 684 0 +-966 -931 411 0 +-945 355 -104 0 +-288 -771 -328 0 +-715 365 -656 0 +774 277 799 0 +-395 -697 33 0 +782 -426 -732 0 +-673 223 738 0 +-884 -130 -674 0 +408 568 -261 0 +-103 623 207 0 +-823 639 -546 0 +-576 700 -11 0 +-625 -51 440 0 +880 -754 14 0 +708 -743 -327 0 +-4 -371 -11 0 +266 314 -844 0 +897 988 934 0 +189 450 869 0 +420 -541 112 0 +599 288 36 0 +-319 -77 749 0 +-421 -906 -222 0 +-793 259 -141 0 +394 -660 -757 0 +-474 959 -24 0 +-543 950 302 0 +-589 538 299 0 +-297 638 250 0 +735 -584 320 0 +-747 -333 -809 0 +801 -705 942 0 +-341 -622 204 0 +73 832 -237 0 +-705 -53 -995 0 +607 -992 328 0 +401 -513 33 0 +803 483 197 0 +129 -281 387 0 +113 401 -110 0 +39 612 928 0 +348 -539 -9 0 +267 -663 -524 0 +-354 376 326 0 +-180 -451 754 0 +-952 -356 521 0 +-127 -645 36 0 +-312 -965 -697 0 +-975 633 159 0 +-770 -713 983 0 +-612 -105 198 0 +329 533 -860 0 +-91 487 -422 0 +560 -586 -206 0 +-104 -317 402 0 +-582 -94 976 0 +897 575 -211 0 +-640 -813 -992 0 +819 -792 297 0 +-312 -337 -194 0 +349 -692 -933 0 +320 459 -413 0 +911 278 787 0 +704 26 -160 0 +102 -923 -831 0 +776 -930 -623 0 +241 -280 -991 0 +158 722 -270 0 +750 -936 707 0 +916 661 334 0 +-441 770 598 0 +418 -677 888 0 +-944 44 621 0 +820 278 -862 0 +-712 -824 272 0 +209 -375 -400 0 +-715 -788 -82 0 +339 706 239 0 +475 -822 428 0 +-341 -132 215 0 +174 39 604 0 +308 400 -774 0 +719 -862 579 0 +-172 -505 -856 0 +-540 -589 -672 0 +-925 816 684 0 +-52 61 -398 0 +363 -177 735 0 +-763 383 -917 0 +-401 830 -359 0 +-779 114 -643 0 +54 138 902 0 +327 -576 -717 0 +418 635 729 0 +-506 773 -711 0 +-950 213 -814 0 +-103 -7 -225 0 +220 -309 539 0 +-925 59 -757 0 +454 986 591 0 +599 -124 -971 0 +730 -721 -825 0 +128 -84 -157 0 +615 602 57 0 +-132 -658 681 0 +-209 -782 354 0 +805 -540 110 0 +596 -230 -939 0 +-513 -169 -183 0 +-184 848 619 0 +-898 -794 -215 0 +16 613 -370 0 +291 -861 990 0 +409 118 318 0 +863 -839 378 0 +-236 -642 -770 0 +-958 300 451 0 +137 -364 465 0 +-169 -728 -981 0 +-320 77 -645 0 +361 -982 674 0 +315 -29 600 0 +685 -645 563 0 +-5 751 8 0 +-287 -979 -119 0 +-532 692 -113 0 +-192 -772 435 0 +44 -801 998 0 +-254 -960 385 0 +-613 81 -822 0 +725 -470 511 0 +335 713 -770 0 +928 390 57 0 +183 -237 277 0 +367 -855 649 0 +249 302 979 0 +577 349 -841 0 +883 340 978 0 +-153 -931 133 0 +465 897 -186 0 +80 26 885 0 +639 386 -674 0 +37 -663 -421 0 +709 749 14 0 +-173 409 -610 0 +-228 -154 534 0 +242 -585 403 0 +-295 -961 978 0 +-284 -915 -588 0 +-895 478 -595 0 +-166 -905 -538 0 +194 449 -232 0 +-355 331 -188 0 +727 202 246 0 +972 -764 350 0 +417 91 -841 0 +864 315 -239 0 +-610 -189 506 0 +69 -354 -365 0 +441 61 -981 0 +75 193 -883 0 +-918 562 -351 0 +686 304 885 0 +595 -30 -446 0 +-997 -338 -487 0 +355 217 -25 0 +104 -311 420 0 +728 -407 748 0 +784 -972 -554 0 +750 791 421 0 +996 -488 -214 0 +791 -797 -480 0 +-944 -999 401 0 +-505 -46 341 0 +-453 759 -660 0 +598 157 -984 0 +-884 52 766 0 +727 767 -869 0 +-663 575 -382 0 +473 -262 -511 0 +475 -78 325 0 +-948 808 -311 0 +-957 -280 29 0 +-19 -685 150 0 +454 500 718 0 +-646 638 278 0 +-287 -705 392 0 +727 -409 677 0 +936 -134 340 0 +-385 -185 -599 0 +774 305 -223 0 +703 184 628 0 +-20 733 -158 0 +-72 -612 -154 0 +965 512 -627 0 +-820 -887 905 0 +-506 364 -368 0 +-224 -572 -74 0 +-173 -724 -946 0 +-735 -856 422 0 +231 -145 704 0 +-739 126 -503 0 +128 525 -716 0 +-491 -261 -838 0 +-25 -325 -811 0 +-160 185 295 0 +631 -61 -692 0 +633 642 -476 0 +703 -681 264 0 +-964 -595 537 0 +-504 -664 615 0 +504 336 -996 0 +434 551 589 0 +-607 604 313 0 +81 -600 -27 0 +-729 -810 977 0 +-716 603 -838 0 +645 -320 297 0 +-12 124 -152 0 +-436 -342 935 0 +-175 -195 925 0 +-786 -848 -276 0 +947 -761 328 0 +539 967 -986 0 +-809 -912 489 0 +999 549 966 0 +74 880 347 0 +596 -863 -22 0 +-249 -521 -60 0 +-977 654 887 0 +545 -813 204 0 +-317 -152 543 0 +515 965 935 0 +153 6 -86 0 +554 -773 100 0 +97 -875 94 0 +-363 852 -331 0 +778 -28 -503 0 +-344 567 -966 0 +-262 -73 997 0 +36 666 -675 0 +345 591 -426 0 +61 -869 -606 0 +605 -934 229 0 +-279 89 -103 0 +-449 -479 -652 0 +365 -570 -651 0 +229 201 479 0 +-352 238 -324 0 +-948 480 -19 0 +-120 -605 -127 0 +-316 875 923 0 +-243 -684 -543 0 +331 640 -429 0 +907 359 -272 0 +-757 446 -794 0 +-118 -684 -570 0 +413 154 -141 0 +270 -850 75 0 +-189 514 797 0 +-685 193 -4 0 +-849 -588 963 0 +489 19 -117 0 +-192 353 496 0 +148 653 206 0 +-475 -610 848 0 +558 919 489 0 +-62 -726 566 0 +-747 -844 772 0 +-342 15 -371 0 +115 -42 150 0 +-724 -171 915 0 +772 -292 470 0 +79 -848 -941 0 +-797 -592 -159 0 +418 247 763 0 +-696 -784 590 0 +-625 -696 -49 0 +134 791 -559 0 +708 -792 -775 0 +-367 -62 -264 0 +-607 -264 -195 0 +663 -500 -307 0 +924 584 458 0 +785 -117 -100 0 +-229 -687 -883 0 +910 -642 -830 0 +149 775 -175 0 +38 498 -827 0 +-621 -212 415 0 +-793 -42 -221 0 +140 886 -74 0 +-654 635 419 0 +624 585 798 0 +401 -604 -820 0 +-279 23 629 0 +-890 783 -106 0 +-842 -506 108 0 +477 864 830 0 +-109 -470 178 0 +443 -598 -328 0 +493 -687 -562 0 +-757 -85 -296 0 +-462 254 -128 0 +-307 -651 653 0 +-47 -560 436 0 +-161 540 597 0 +-39 510 -708 0 +954 594 536 0 +994 106 -969 0 +446 431 -196 0 +-342 -719 -451 0 +946 -547 -167 0 +-678 -968 -817 0 +643 941 -254 0 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp100.dat b/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp100.dat new file mode 100644 index 0000000..9d358cf --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp100.dat @@ -0,0 +1,307 @@ +100 + +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 +3 +6 +9 +12 +15 + +5 +10 +15 +20 +25 +29 +34 +39 +44 +49 +53 +58 +63 +68 +73 +77 +82 +87 +92 +97 +101 +106 +111 +116 +121 +125 +130 +135 +140 +145 +149 +154 +159 +164 +169 +173 +178 +183 +188 +193 +197 +202 +207 +212 +217 +221 +226 +231 +236 +241 +245 +250 +255 +260 +265 +269 +274 +279 +284 +289 +293 +298 +303 +308 +313 +317 +322 +327 +332 +337 +341 +346 +351 +356 +361 +365 +370 +375 +380 +385 +389 +394 +399 +404 +409 +413 +418 +423 +428 +433 +437 +442 +447 +452 +457 +461 +466 +471 +476 +481 + +60.000000 +40.000000 +7.000000 +3.000000 +50.000000 +120.000000 +80.000000 +7.000000 +3.000000 +100.000000 +180.000000 +120.000000 +7.000000 +3.000000 +150.000000 +240.000000 +160.000000 +7.000000 +3.000000 +200.000000 +300.000000 +200.000000 +7.000000 +3.000000 +250.000000 +360.000000 +240.000000 +7.000000 +3.000000 +300.000000 +420.000000 +280.000000 +7.000000 +3.000000 +350.000000 +480.000000 +320.000000 +7.000000 +3.000000 +400.000000 +540.000000 +360.000000 +7.000000 +3.000000 +450.000000 +600.000000 +400.000000 +7.000000 +3.000000 +500.000000 +660.000000 +440.000000 +7.000000 +3.000000 +550.000000 +720.000000 +480.000000 +7.000000 +3.000000 +600.000000 +780.000000 +520.000000 +7.000000 +3.000000 +650.000000 +840.000000 +560.000000 +7.000000 +3.000000 +700.000000 +900.000000 +600.000000 +7.000000 +3.000000 +750.000000 +960.000000 +640.000000 +7.000000 +3.000000 +800.000000 +1020.000000 +680.000000 +7.000000 +3.000000 +850.000000 +1080.000000 +720.000000 +7.000000 +3.000000 +900.000000 +1140.000000 +760.000000 +7.000000 +3.000000 +950.000000 +1200.000000 +800.000000 +7.000000 +3.000000 +1000.000000 + +200 +) diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp20.dat b/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp20.dat new file mode 100644 index 0000000..9dde3f3 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/MTTP-instances/mttp20.dat @@ -0,0 +1,84 @@ +20 + +2 +4 +1 +7 +4 +3 +5 +2 +4 +7 +2 +9 +8 +6 +1 +4 +9 +7 +8 +2 + +3 +5 +6 +8 +10 +15 +16 +20 +25 +29 +30 +36 +49 +59 +80 +81 +89 +97 +100 +105 + +15.000000 +20.000000 +16.000000 +19.000000 +10.000000 +25.000000 +17.000000 +18.000000 +21.000000 +17.000000 +31.000000 +2.000000 +26.000000 +42.000000 +50.000000 +19.000000 +17.000000 +21.000000 +22.000000 +13.000000 + + +00001111111111111111 70.000000 + +01001110111011111111 70.000000 + +01101101101011111111 70.000000 + +01101101111011110111 70.000000 + +01101101111111101111 70.000000 + +10001111111011111110 70.000000 + +10100111011111111111 70.000000 + +10100111111011101111 70.000000 + +10100111111111111011 70.000000 +) diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/format.txt b/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/format.txt new file mode 100644 index 0000000..179a679 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/format.txt @@ -0,0 +1 @@ +// dimension of the bitstring. diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/onemax10.txt b/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/onemax10.txt new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/ONEMAX-instances/onemax10.txt @@ -0,0 +1 @@ +10 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS10.txt b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS20.txt b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/RAS20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/format.txt b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/RAS-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/RND-instances/rnd149.txt b/ProyectoFinal/CHC/malva/ProblemInstances/RND-instances/rnd149.txt new file mode 100644 index 0000000..15c44e9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/RND-instances/rnd149.txt @@ -0,0 +1 @@ +149 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH10.txt b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH20.txt b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/SPH20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/format.txt b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/SPHERE-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/format.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/format.txt new file mode 100644 index 0000000..abccebe --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/format.txt @@ -0,0 +1,3 @@ +// Number of customers, Vehicle capacity, Maximum time per route, Service time and best known cost +// Depot Coordenates +// Customer coordenates and demand diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpinfo.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpinfo.txt new file mode 100644 index 0000000..a63a622 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpinfo.txt @@ -0,0 +1,47 @@ +There are currently 24 data files. + +The first set of data files are the 10 test problems from +Chapter 9 of S.Eilon, C.D.T.Watson-Gandy and N.Christofides +"Distribution management: mathematical modelling and +practical analysis" Griffin, London 1971. + +Test problems 1, 2, ..., 10 from Chapter 9 are available +in files vrp1, vrp2, ..., vrp10 respectively. + +The format of these data files is apparent from the tables +of data given in the above reference. + +The second set of data files are the 14 test problems from +Chapter 11 of N.Christofides, A.Mingozzi, P.Toth and C.Sandi +(eds) "Combinatorial optimization", John Wiley, Chichester 1979. + +Test problems 1, 2, ..., 14 from Chapter 11 are available +in files vrpnc1, vrpnc2, ..., vrpnc14 respectively. + +The format of these data files is: +number of customers, vehicle capacity, maximum route time, drop time +depot x-coordinate, depot y-coordinate +for each customer in turn: x-coordinate, y-coordinate, quantity + +Both sets of files are of size 15Kb (approximately). + + + +OTHER SOURCES + +Test data for vehicle routing problems is also available +using the Web from http://www-apache.imag.fr/~paugerat/VRP/INSTANCES + +A variety of vehicle routing problems are also available from the +elib library: +telnet elib.zib.de and login as elib +WWW access available at: +ftp://ftp.zib.de/pub/Packages/mp-testdata/index.html + + + +A full listing of the problem areas covered by OR-library can +be found in the file info + +ftp access available at mscmga.ms.ic.ac.uk +WWW access available at http://mscmga.ms.ic.ac.uk/ diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc1.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc1.txt new file mode 100644 index 0000000..fb9bd54 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc1.txt @@ -0,0 +1,52 @@ + 50 160 999999 0 524.61 + 30 40 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc10.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc10.txt new file mode 100644 index 0000000..bd6fc1b --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc10.txt @@ -0,0 +1,201 @@ + 199 200 200 10 865.94 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc11.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc11.txt new file mode 100644 index 0000000..adea50e --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc11.txt @@ -0,0 +1,122 @@ + 120 200 999999 0 866.37 + 10 45 + 25 1 25 + 25 3 7 + 31 5 13 + 32 5 6 + 31 7 14 + 32 9 5 + 34 9 11 + 46 9 19 + 35 7 5 + 34 6 15 + 35 5 15 + 47 6 17 + 40 5 13 + 39 3 12 + 36 3 18 + 73 6 13 + 73 8 18 + 24 36 12 + 76 6 17 + 76 10 4 + 76 13 7 + 78 3 12 + 78 9 13 + 79 3 8 + 79 5 16 + 79 11 15 + 82 3 6 + 82 7 5 + 90 15 9 + 84 3 11 + 84 5 10 + 84 9 3 + 85 1 7 + 87 5 2 + 85 8 4 + 87 7 4 + 86 41 18 + 86 44 14 + 86 46 12 + 85 55 17 + 89 43 20 + 89 46 14 + 89 52 16 + 92 42 10 + 92 52 9 + 94 42 11 + 94 44 7 + 94 48 13 + 96 42 5 + 99 46 4 + 99 50 21 + 83 80 13 + 83 83 11 + 85 81 12 + 85 85 14 + 85 89 10 + 87 80 8 + 87 86 16 + 90 77 19 + 90 88 5 + 93 82 17 + 93 84 7 + 93 89 16 + 94 86 14 + 95 80 17 + 99 89 13 + 37 83 17 + 50 80 13 + 35 85 14 + 35 87 16 + 44 86 7 + 46 89 13 + 46 83 9 + 46 87 11 + 46 89 35 + 48 83 5 + 50 85 28 + 50 88 7 + 54 86 3 + 54 90 10 + 10 35 7 + 10 40 12 + 18 30 11 + 17 35 10 + 16 38 8 + 14 40 11 + 15 42 21 + 11 42 4 + 18 40 15 + 21 39 16 + 20 40 4 + 18 41 16 + 20 44 7 + 22 44 10 + 16 45 9 + 20 45 11 + 25 45 17 + 30 55 12 + 20 50 11 + 22 51 7 + 18 49 9 + 16 48 11 + 20 55 12 + 18 53 7 + 14 50 8 + 15 51 6 + 16 54 5 + 28 33 12 + 33 38 13 + 30 50 7 + 13 40 7 + 15 36 8 + 18 31 11 + 25 37 13 + 30 46 11 + 25 52 10 + 16 33 7 + 25 35 4 + 5 40 20 + 5 50 13 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc12.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc12.txt new file mode 100644 index 0000000..939f5dd --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc12.txt @@ -0,0 +1,102 @@ + 100 200 999999 0 1541.14 + 40 50 + 45 68 10 + 45 70 30 + 42 66 10 + 42 68 10 + 42 65 10 + 40 69 20 + 40 66 20 + 38 68 20 + 38 70 10 + 35 66 10 + 35 69 10 + 25 85 20 + 22 75 30 + 22 85 10 + 20 80 40 + 20 85 40 + 18 75 20 + 15 75 20 + 15 80 10 + 30 50 10 + 30 52 20 + 28 52 20 + 28 55 10 + 25 50 10 + 25 52 40 + 25 55 10 + 23 52 10 + 23 55 20 + 20 50 10 + 20 55 10 + 10 35 20 + 10 40 30 + 8 40 40 + 8 45 20 + 5 35 10 + 5 45 10 + 2 40 20 + 0 40 30 + 0 45 20 + 35 30 10 + 35 32 10 + 33 32 20 + 33 35 10 + 32 30 10 + 30 30 10 + 30 32 30 + 30 35 10 + 28 30 10 + 28 35 10 + 26 32 10 + 25 30 10 + 25 35 10 + 44 5 20 + 42 10 40 + 42 15 10 + 40 5 30 + 40 15 40 + 38 5 30 + 38 15 10 + 35 5 20 + 50 30 10 + 50 35 20 + 50 40 50 + 48 30 10 + 48 40 10 + 47 35 10 + 47 40 10 + 45 30 10 + 45 35 10 + 95 30 30 + 95 35 20 + 53 30 10 + 92 30 10 + 53 35 50 + 45 65 20 + 90 35 10 + 88 30 10 + 88 35 20 + 87 30 10 + 85 25 10 + 85 35 30 + 75 55 20 + 72 55 10 + 70 58 20 + 68 60 30 + 66 55 10 + 65 55 20 + 65 60 30 + 63 58 10 + 60 55 10 + 60 60 10 + 67 85 20 + 65 85 40 + 65 82 10 + 62 80 30 + 60 80 10 + 60 85 30 + 58 75 20 + 55 80 10 + 55 85 20 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc13.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc13.txt new file mode 100644 index 0000000..975ff61 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc13.txt @@ -0,0 +1,122 @@ + 120 200 720 50 1162.55 + 10 45 + 25 1 25 + 25 3 7 + 31 5 13 + 32 5 6 + 31 7 14 + 32 9 5 + 34 9 11 + 46 9 19 + 35 7 5 + 34 6 15 + 35 5 15 + 47 6 17 + 40 5 13 + 39 3 12 + 36 3 18 + 73 6 13 + 73 8 18 + 24 36 12 + 76 6 17 + 76 10 4 + 76 13 7 + 78 3 12 + 78 9 13 + 79 3 8 + 79 5 16 + 79 11 15 + 82 3 6 + 82 7 5 + 90 15 9 + 84 3 11 + 84 5 10 + 84 9 3 + 85 1 7 + 87 5 2 + 85 8 4 + 87 7 4 + 86 41 18 + 86 44 14 + 86 46 12 + 85 55 17 + 89 43 20 + 89 46 14 + 89 52 16 + 92 42 10 + 92 52 9 + 94 42 11 + 94 44 7 + 94 48 13 + 96 42 5 + 99 46 4 + 99 50 21 + 83 80 13 + 83 83 11 + 85 81 12 + 85 85 14 + 85 89 10 + 87 80 8 + 87 86 16 + 90 77 19 + 90 88 5 + 93 82 17 + 93 84 7 + 93 89 16 + 94 86 14 + 95 80 17 + 99 89 13 + 37 83 17 + 50 80 13 + 35 85 14 + 35 87 16 + 44 86 7 + 46 89 13 + 46 83 9 + 46 87 11 + 46 89 35 + 48 83 5 + 50 85 28 + 50 88 7 + 54 86 3 + 54 90 10 + 10 35 7 + 10 40 12 + 18 30 11 + 17 35 10 + 16 38 8 + 14 40 11 + 15 42 21 + 11 42 4 + 18 40 15 + 21 39 16 + 20 40 4 + 18 41 16 + 20 44 7 + 22 44 10 + 16 45 9 + 20 45 11 + 25 45 17 + 30 55 12 + 20 50 11 + 22 51 7 + 18 49 9 + 16 48 11 + 20 55 12 + 18 53 7 + 14 50 8 + 15 51 6 + 16 54 5 + 28 33 12 + 33 38 13 + 30 50 7 + 13 40 7 + 15 36 8 + 18 31 11 + 25 37 13 + 30 46 11 + 25 52 10 + 16 33 7 + 25 35 4 + 5 40 20 + 5 50 13 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc14.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc14.txt new file mode 100644 index 0000000..02946d9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc14.txt @@ -0,0 +1,102 @@ + 100 200 1040 90 1395.85 + 40 50 + 45 68 10 + 45 70 30 + 42 66 10 + 42 68 10 + 42 65 10 + 40 69 20 + 40 66 20 + 38 68 20 + 38 70 10 + 35 66 10 + 35 69 10 + 25 85 20 + 22 75 30 + 22 85 10 + 20 80 40 + 20 85 40 + 18 75 20 + 15 75 20 + 15 80 10 + 30 50 10 + 30 52 20 + 28 52 20 + 28 55 10 + 25 50 10 + 25 52 40 + 25 55 10 + 23 52 10 + 23 55 20 + 20 50 10 + 20 55 10 + 10 35 20 + 10 40 30 + 8 40 40 + 8 45 20 + 5 35 10 + 5 45 10 + 2 40 20 + 0 40 30 + 0 45 20 + 35 30 10 + 35 32 10 + 33 32 20 + 33 35 10 + 32 30 10 + 30 30 10 + 30 32 30 + 30 35 10 + 28 30 10 + 28 35 10 + 26 32 10 + 25 30 10 + 25 35 10 + 44 5 20 + 42 10 40 + 42 15 10 + 40 5 30 + 40 15 40 + 38 5 30 + 38 15 10 + 35 5 20 + 50 30 10 + 50 35 20 + 50 40 50 + 48 30 10 + 48 40 10 + 47 35 10 + 47 40 10 + 45 30 10 + 45 35 10 + 95 30 30 + 95 35 20 + 53 30 10 + 92 30 10 + 53 35 50 + 45 65 20 + 90 35 10 + 88 30 10 + 88 35 20 + 87 30 10 + 85 25 10 + 85 35 30 + 75 55 20 + 72 55 10 + 70 58 20 + 68 60 30 + 66 55 10 + 65 55 20 + 65 60 30 + 63 58 10 + 60 55 10 + 60 60 10 + 67 85 20 + 65 85 40 + 65 82 10 + 62 80 30 + 60 80 10 + 60 85 30 + 58 75 20 + 55 80 10 + 55 85 20 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc2.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc2.txt new file mode 100644 index 0000000..214012a --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc2.txt @@ -0,0 +1,77 @@ + 75 140 999999 0 835.26 + 40 40 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 + 15 56 22 + 29 39 12 + 54 38 19 + 55 57 22 + 67 41 16 + 10 70 7 + 6 25 26 + 65 27 14 + 40 60 21 + 70 64 24 + 64 4 13 + 36 6 15 + 30 20 18 + 20 30 11 + 15 5 28 + 50 70 9 + 57 72 37 + 45 42 30 + 38 33 10 + 50 4 8 + 66 8 11 + 59 5 3 + 35 60 1 + 27 24 6 + 40 20 10 + 40 37 20 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc3.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc3.txt new file mode 100644 index 0000000..8bfcc47 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc3.txt @@ -0,0 +1,102 @@ + 100 200 999999 0 826.14 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc4.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc4.txt new file mode 100644 index 0000000..3faf64a --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc4.txt @@ -0,0 +1,152 @@ + 150 200 999999 0 819.56 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc5.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc5.txt new file mode 100644 index 0000000..3cacfb7 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc5.txt @@ -0,0 +1,201 @@ + 199 200 999999 0 1042.11 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc6.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc6.txt new file mode 100644 index 0000000..449fd5c --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc6.txt @@ -0,0 +1,52 @@ + 50 160 200 10 1028.42 + 30 40 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc7.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc7.txt new file mode 100644 index 0000000..1b8aa97 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc7.txt @@ -0,0 +1,77 @@ + 75 140 160 10 1291.45 + 40 40 + 22 22 18 + 36 26 26 + 21 45 11 + 45 35 30 + 55 20 21 + 33 34 19 + 50 50 15 + 55 45 16 + 26 59 29 + 40 66 26 + 55 65 37 + 35 51 16 + 62 35 12 + 62 57 31 + 62 24 8 + 21 36 19 + 33 44 20 + 9 56 13 + 62 48 15 + 66 14 22 + 44 13 28 + 26 13 12 + 11 28 6 + 7 43 27 + 17 64 14 + 41 46 18 + 55 34 17 + 35 16 29 + 52 26 13 + 43 26 22 + 31 76 25 + 22 53 28 + 26 29 27 + 50 40 19 + 55 50 10 + 54 10 12 + 60 15 14 + 47 66 24 + 30 60 16 + 30 50 33 + 12 17 15 + 15 14 11 + 16 19 18 + 21 48 17 + 50 30 21 + 51 42 27 + 50 15 19 + 48 21 20 + 12 38 5 + 15 56 22 + 29 39 12 + 54 38 19 + 55 57 22 + 67 41 16 + 10 70 7 + 6 25 26 + 65 27 14 + 40 60 21 + 70 64 24 + 64 4 13 + 36 6 15 + 30 20 18 + 20 30 11 + 15 5 28 + 50 70 9 + 57 72 37 + 45 42 30 + 38 33 10 + 50 4 8 + 66 8 11 + 59 5 3 + 35 60 1 + 27 24 6 + 40 20 10 + 40 37 20 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc8.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc8.txt new file mode 100644 index 0000000..0383887 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc8.txt @@ -0,0 +1,102 @@ + 100 200 230 10 555.43 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 diff --git a/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc9.txt b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc9.txt new file mode 100644 index 0000000..1910e87 --- /dev/null +++ b/ProyectoFinal/CHC/malva/ProblemInstances/VRP-instances/vrpnc9.txt @@ -0,0 +1,152 @@ + 150 200 200 10 909.68 + 35 35 + 41 49 10 + 35 17 7 + 55 45 13 + 55 20 19 + 15 30 26 + 25 30 3 + 20 50 5 + 10 43 9 + 55 60 16 + 30 60 16 + 20 65 12 + 50 35 19 + 30 25 23 + 15 10 20 + 30 5 8 + 10 20 19 + 5 30 2 + 20 40 12 + 15 60 17 + 45 65 9 + 45 20 11 + 45 10 18 + 55 5 29 + 65 35 3 + 65 20 6 + 45 30 17 + 35 40 16 + 41 37 16 + 64 42 9 + 40 60 21 + 31 52 27 + 35 69 23 + 53 52 11 + 65 55 14 + 63 65 8 + 2 60 5 + 20 20 8 + 5 5 16 + 60 12 31 + 40 25 9 + 42 7 5 + 24 12 5 + 23 3 7 + 11 14 18 + 6 38 16 + 2 48 1 + 8 56 27 + 13 52 36 + 6 68 30 + 47 47 13 + 49 58 10 + 27 43 9 + 37 31 14 + 57 29 18 + 63 23 2 + 53 12 6 + 32 12 7 + 36 26 18 + 21 24 28 + 17 34 3 + 12 24 13 + 24 58 19 + 27 69 10 + 15 77 9 + 62 77 20 + 49 73 25 + 67 5 25 + 56 39 36 + 37 47 6 + 37 56 5 + 57 68 15 + 47 16 25 + 44 17 9 + 46 13 8 + 49 11 18 + 49 42 13 + 53 43 14 + 61 52 3 + 57 48 23 + 56 37 6 + 55 54 26 + 15 47 16 + 14 37 11 + 11 31 7 + 16 22 41 + 4 18 35 + 28 18 26 + 26 52 9 + 26 35 15 + 31 67 3 + 15 19 1 + 22 22 2 + 18 24 22 + 26 27 27 + 25 24 20 + 22 27 11 + 25 21 12 + 19 21 10 + 20 26 9 + 18 18 17 + 37 52 7 + 49 49 30 + 52 64 16 + 20 26 9 + 40 30 21 + 21 47 15 + 17 63 19 + 31 62 23 + 52 33 11 + 51 21 5 + 42 41 19 + 31 32 29 + 5 25 23 + 12 42 21 + 36 16 10 + 52 41 15 + 27 23 3 + 17 33 41 + 13 13 9 + 57 58 28 + 62 42 8 + 42 57 8 + 16 57 16 + 8 52 10 + 7 38 28 + 27 68 7 + 30 48 15 + 43 67 14 + 58 48 6 + 58 27 19 + 37 69 11 + 38 46 12 + 46 10 23 + 61 33 26 + 62 63 17 + 63 69 6 + 32 22 9 + 45 35 15 + 59 15 14 + 5 6 7 + 10 17 27 + 21 10 13 + 5 64 11 + 30 15 16 + 39 10 10 + 32 39 5 + 25 32 25 + 25 55 17 + 48 28 18 + 56 37 10 diff --git a/ProyectoFinal/CHC/malva/README.md b/ProyectoFinal/CHC/malva/README.md new file mode 100644 index 0000000..53d6d5d --- /dev/null +++ b/ProyectoFinal/CHC/malva/README.md @@ -0,0 +1,278 @@ +## What is Malva? + +Malva is a fork of the MALLBA project. MALLBA is an effort to develop, in an integrated way, a +library of skeletons for combinatorial optimization (including exact, heuristic and hybrid methods) +that can deal with parallelism in a user-friendly and, at the same time, efficient manner. +Its three target environments are sequential computers, LANs of workstations and WANs. The main features of MALLBA are: + +* Integration of all the skeletons under the same design principles. +* Facility to switch from sequential to parallel optimization engines. +By providing sequential implementations users obtain parallel implementations. +* Cooperation between engines makes possible to provide more powerful hybrid engines. +* Ready to use on commodity machines. +* Flexible and extensible software architecture. New skeletons can easily be added, alternative communication layers +can be used, etc. + +## How to install and compile Malva + +First of all, you have to install MPICH library. Get the instructions here: http://www.mpich.org/. In OSX, you can just +type: + + brew install mpich --disable-fortran + +Disabling Fortran is needed since we are working with C++ instead of Fortran. + +After that, you have to clone this repository using `git clone https://github.com/gabrielfagundez/malva`, and configure Malva modifying the `environment` file. + +Then, execute the following command: + + make all + +Your Malva directory should contain the following content after the make: + +``` + -rw-r--r-- 1 user users 378 sep 24 09:39 Makefile + drwxr-xr-x 4 user users 4096 sep 24 09:48 ProblemInstances + -rw-r--r-- 1 user users 345 sep 24 16:29 environment + drwxr-xr-x 2 user users 4096 sep 24 16:43 inc + drwxr-xr-x 2 user users 4096 sep 24 17:49 lib + drwxr-xr-x 5 user users 4096 sep 24 09:41 rep + drwxr-xr-x 2 user users 4096 sep 24 17:49 src +``` + +## Testing the installation + +Go to `MALLBA_DIR/rep_new/CHC` or `MALLBA_DIR/rep_new/GA` and execute `make SEQ` or `make LAN`. If you have in your console +the result of the execution, everything looks great! + +## Important notes + +The only new fully-functional algorithms are the GA and the CHC. + +## Architecture + +Mallba skeletons are based on the separation of two concepts: the concrete problem to be solved and the general +resolution method to be used. They can be seen as generic templates that just need to be instantiated with the +features of a problem in order to solve it. All features related to the selected generic resolution method and +its interaction with the concrete problem are implemented by the skeleton. While the particular features related +to the problem must be given by the user, the knowledge to parallelize the execution of the resolution method is +implemented in the skeleton, so that users do not need to deal with parallelism issues. + +The design of the Mallba library focuses on easy to use skeletons and general and efficient implementations. +To achieve both objectives, the C++ programming language was selected due to its high level, modularity, +flexibility and efficiency features. We have reduced to a minimum the use of inheritance and virtual methods in +order to provide better efficiency and ease of use. To instantiate most problems, a basic knowledge of C++ is enough, +and only sequential code without side effects is needed. + +Skeletons are implemented by a set of required and provided C++ classes that represent an abstraction of the entities +participating in the resolution method. The provided classes implement internal aspects of the skeleton in a +problem-independent way. The required classes specify information and behavior related to the problem. +This conceptual separation allows us to define required classes with a fixed interface but without any implementation, +so that provided classes can use required classes in a generic way. + +More specifically, each skeleton includes the Problem and Solution required classes, that encapsulate the +problem-dependent entities needed by the resolution method. The Problem class abstracts the features of the +problem that are relevant to the selected optimization method. The Solution class abstracts the features of the +feasible solutions that are relevant to the selected resolution method. Depending on the skeleton, other classes +may be required. On the other hand, each skeleton offers two provided classes: Solver and SetUpParams. The former +abstracts the selected resolution method. The later contains the setup parameters needed to perform the execution +(e.g. number of iterations, number of independent runs, parameters guiding the search, etc.). The Solver class provides +methods to run the resolution scheme and methods to consult its progress or change its state. The only information the +solver needs is an instance of the problem to solve and the setup parameters. In order to enable an skeleton to have +different solver engines, the Solver class defines a unique interface and provides several subclasses that provide +different sequential and parallel implementations (Solver_Seq, Solver_Lan and Solver_Wan). In Fig. 1 is shown the +common design of Mallba skeletons. + + + +## Implementation + +The implementation of each skeleton is contained in three files: + +* <skeleton>.hh: The file containing the definition of all classes (provides and requires). +* <skeleton>.pro.cc: The file containing the source code of the classes needed for the internal implementation of the method. +* <skeleton>.req.cc: The source file where all the required classes will be implemented. + +In additional, the user must configure the method parameters in the file <skeleton>.cfg. + +## Supported Algorithms + +### Genetic Algorithm + +A Genetic Algorithm is an evolutionary computation technique inspired by the principles of natural selection to search +a solution space. It evolves a population of individuals encoded as chromosomes by creating new generations of +offsprings through an iterative process until some convergence criteria or conditions are met. The best chromosome +generated is then decoded, providing the corresponding solution. The underlying reproduction process is mainly aimed +at improving the fitness of individuals, a measure of profit, utility or goodness to be maximized (or minimized) while +exploring the solution space. The algorithm applies stochastic operators such as selection, crossover, and mutation, +on an initially random population in order to compute a new generation of individuals. The whole process is sketched +in the following figure. + +``` + 1 t = 0 + 2 initialize P(t) + 3 evaluate structures in P(t) + 4 while not end do + 5 t = t + 1 + 6 select C(t) from P(t-1) + 7 recombine structures in C(t) forming C'(t) + 8 mutate structures in C'(t) forming C''(t) + 9 evaluate structures in C''(t) +10 replace P(t) from C''(t) and/or P(t-1) +``` + +It can be seen that the algorithm comprises three major stages: selection, reproduction and replacement. During the +selection stage, a temporary population is created in which the fittest individuals (those corresponding to the best +solutions contained in the population) have a higher number of instances than those less fit (natural selection). The +reproductive operators are applied to the individuals in this population yielding a new population. Finally, individuals +of the original population are substituted by the new created individuals. This replacement usually tries to keep the +best individuals deleting the worst ones. The whole process is repeated until a certain termination criterion is +achieved (usually after a given number of iterations). + +The Genetic Algorithm skeleton (GA) requires the classes: + +* Problem +* Solution +* Crossover +* Mutation + +The class Problem corresponds to the definition of a problem instance. The skeleton filler must provide a complete +definition of this class. + +The class Solution corresponds to the definition of a solution (feasible or not) of a problem instance. The skeleton +filler must provide a complete definition of the class Solution. + +The class Crossover corresponds to the definition of a crossover operator. The skeleton filler must provide a complete +definition of this class. + +And finally, the class Mutation corresponds to the definition of a mutation operator. The skeleton filler must provide +a complete definition of this class. + +In adition, the user must configure the following algorithm parameters (in file GA.cfg): + +* number of independent runs. +* number of generations. +* size of population. +* size of offsprings in each generation. +* replace mode (if replaces parents for offsprings, or only offsprings may be new parents). +* Selection operators parameters (selection of parents and selection of offsprings parameters). +* Intra operators parameters (crossover and mutation parameters). +* Inter operators (operators to apply between sub-populations) parameters: operator number, operator rate, number of individuals and selection of individual to send and replace. +* Parallel Configuracion: interval of generation to refresh global state, running mode (synchronized or asyncronized) and interval of generations to check solutions from other populations. + +There are several basic steps to running a problem solve with GA skeleton: + +* Change to the problem directory + + `cd Mallba/rep/GA/problem` + +* Compile skeleton. + + `make` + +* Configure algorithm parameters (GA.cfg file) + +* Run problem: +Sequential Version: + +``` +make SEQ + or +MainSeq GA.cfg_path instance_path res_file_path +``` + +Parallel Version: + +Configure Config.cfg file. +Configure pgfileLan (or pgfileWan) : machines where we run the program. +Run + +``` +make LAN + or +make WAN +``` + +### CHC + +A CHC is a non-traditional GA which combines a conservative selection strategy (that always preserves the best +individuals found so far) with a highly disruptive recombination (HUX) that produces offsprings that are maximally +different from their two parents. The traditional though of preferring a recombination operator with a low disrupting +properties may not hold when such a conservative selection strategy is used. On the contrary, certain highly disruptive +crossover operator provide more effective search in many problems, which represents the core idea behind the + +CHC search method. This algorithm introduce a new bias against mating individuals who are too similar (incest +prevention). Mutation is not performed, instead, a restart process re-introduces diversity whenever convergence is +detected. + +``` + 1 t = 0 + 2 initialize P(t) + 3 evaluate structures in P(t) + 4 while not end do + 5 t = t + 1 + 6 select: C(t) = P(t-1) + 7 recombine: C'(t) = 'incest prevention' + HUX(C'(t)) + 8 evaluate structures in C'(t) + 9 replace P(t) from C''(t) and P(t-1) +10 if convergence(P(t)) +11 diverge P(t) +``` + +The CHC method skeleton (CHC) requires the classes: + +* Problem +* Solution + +The class Problem corresponds to the definition of a problem instance. The skeleton filler must provide a complete +definition of this class. + +And finally, the class Solution corresponds to the definition of a solution (feasible or not) of a problem instance. +The skeleton filler must provide a complete definition of the class Solution. + +In adition, the user must configure the following algorithm parameters (in file CHC.cfg): + +* number of independent runs. +* number of generations. +* size of population. +* Selection operator parameters (selection of new parents and the diverge method that the algorithm uses whenever the +convergence is detected). +* Intra operators parameters (crossover and mutation parameters). +* Inter operators (operators to apply between sub-populations) parameters: operator number, operator rate, number of +individuals and selection of individual to send and replace. +* Parallel Configuracion: interval of generation to refresh global state, running mode (synchronized or asyncronized) +and interval of generations to check solutions from other populations. + +There are several basic steps to running a problem solve with CHC skeleton: + +* Change to the problem directory + + `cd Mallba/rep/CHC/problem` + +* Compile skeleton + + `make` + +* Configure algorithm parameters (CHC.cfg file) + +* Run problem: + +Sequential Version: + +``` +make SEQ + or +MainSeq GA.cfg_path instance_path res_file_path +``` + +Parallel Version: + +Configure Config.cfg file. +Configure pgfileLan (or pgfileWan) : machines where we run the program. +Run + +``` +make LAN + or +make WAN +``` diff --git a/ProyectoFinal/CHC/malva/environment b/ProyectoFinal/CHC/malva/environment new file mode 100644 index 0000000..4976de6 --- /dev/null +++ b/ProyectoFinal/CHC/malva/environment @@ -0,0 +1,19 @@ +# Malva Configuration. +MALLBA_DIR=/ens/home01/g/gonzalo.menendez/AEPractico/malva + +# MPI library +MPI_BIN=/lib64/mpich/bin +# Malva information +MALLBA_INC=${MALLBA_DIR}/src +MALLBA_LIB=${MALLBA_DIR}/lib +MALLBA_SRC=${MALLBA_DIR}/src +MALLBA_REP=${MALLBA_DIR}/rep + +# Run variables +CXX=$(MPI_BIN)/mpic++ +RUN=$(MPI_BIN)/mpirun + +# Other options: -g for debugging and -pg for profiling +CPPFLAGS=-I$(MALLBA_INC) -Wno-deprecated -O3 +LDFLAGS=-L$(MALLBA_LIB) +LOADLIBES=-lmallba -lm diff --git a/ProyectoFinal/CHC/malva/inc/Mallba b/ProyectoFinal/CHC/malva/inc/Mallba new file mode 100644 index 0000000..5cd551c --- /dev/null +++ b/ProyectoFinal/CHC/malva/inc/Mallba @@ -0,0 +1 @@ +../src \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/inc/inc.env b/ProyectoFinal/CHC/malva/inc/inc.env new file mode 100644 index 0000000..3976b86 --- /dev/null +++ b/ProyectoFinal/CHC/malva/inc/inc.env @@ -0,0 +1 @@ +ln -s ../src Mallba diff --git a/ProyectoFinal/CHC/malva/lib/Makefile b/ProyectoFinal/CHC/malva/lib/Makefile new file mode 100644 index 0000000..5bacf25 --- /dev/null +++ b/ProyectoFinal/CHC/malva/lib/Makefile @@ -0,0 +1,8 @@ +all: + rm -f libmallba.a + ar -r libmallba.a ../src/*.o + ranlib libmallba.a + +clean: + rm -f libmallba.a + diff --git a/ProyectoFinal/CHC/malva/lib/libmallba.a b/ProyectoFinal/CHC/malva/lib/libmallba.a new file mode 100644 index 0000000000000000000000000000000000000000..db7f3cab7df60324f9676e75019a0ef727333a3e GIT binary patch literal 34998 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.cfg b/ProyectoFinal/CHC/malva/rep/CHC/CHC.cfg new file mode 100644 index 0000000..0f6c796 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/CHC.cfg @@ -0,0 +1,15 @@ +10 // number of independent runs +100 // number of generations +60 // number of individuals +1 // display state ? +Selection-Parameters // selections to apply +0.9 1 0.5 // selection parameter , diverge operator & its probability +Intra-Operators // operators to apply in the population +0 0.8 // crossover & its probability +Inter-Operators // operators to apply between this population and anothers +0 25 5 1 3 1 5 // operator number, operator rate, number of individuals, selection of indidivual to send and remplace +LAN-configuration +101 // refresh global state +1 // 0: running in asynchronized mode / 1: running in synchronized mode +1 // interval of generations to check solutions from other populations + diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.hh b/ProyectoFinal/CHC/malva/rep/CHC/CHC.hh new file mode 100644 index 0000000..0c89fe4 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/CHC.hh @@ -0,0 +1,909 @@ +/********************************************************************************************************* +*** *** +*** CHC Skeleton v1.5 *** +*** Developed by: Gabriel Jesús Luque Polo *** +*** *** +*** Last Update: 30-01-2004 *** +*** *** +**********************************************************************************************************/ + +#ifndef INC_CHC +#define INC_CHC +#include "CHCstructures.hh" + +skeleton CHC +{ +#define MAX_USER_OP 5 +#define MAX_PROB_PER_OP 5 + + provides class SetUpParams; + provides class Statistics; + provides class Population; + provides class Intra_Operator; + provides class Crossover; + provides class Diverge; + provides class Inter_Operator; + provides class Migration; + provides class Selection; + provides class Selection_New_Population; + provides class Selection_Parents; + provides class Operator_Pool; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + provides class StopCondition; + + requires class Problem; + requires class Solution; + requires class UserStatistics; + requires class User_Operator; + requires class StopCondition_1; + requires bool terminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + int dimension() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness () const; + unsigned int size() const; + + int lengthInBits() const; + void flip(const int index); + bool equalb(const int index,Solution &s); + void swap(const int index, Solution &s); + void invalid(); + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + unsigned long nb_evaluation_best_found_trial; + unsigned long nb_iteration_best_found_trial; + double best_cost_trial; + double worst_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Intra_Operator ( clase abstracta ) -------------------------------------------------------------- + + provides class Intra_Operator + { + protected: + unsigned int _number_operator; + float *probability; + + public: + Intra_Operator(const unsigned int _number_op); + virtual ~Intra_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const Intra_Operator& intra); + + virtual void execute(Rarray<Solution*>& sols) const=0; + virtual void setup(char line[MAX_BUFFER]) = 0; + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const=0; + virtual void UpdateFromState(const StateCenter& _sc)=0; + }; + +// Crossover ---------------------------------------------------------------------------------- + + provides class Crossover: public Intra_Operator + { + public: + Crossover(); + virtual ~Crossover(); + + friend ostream& operator << (ostream& os, const Crossover& cross); + + void cross(Solution &sol1,Solution &sol2) const; + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Diverge ---------------------------------------------------------------------------------- + + provides class Diverge: public Intra_Operator + { + public: + Diverge(); + virtual ~Diverge(); + + friend ostream& operator<< (ostream& os, const Diverge& diverge); + + void diverge(Solution& s) const; + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// User_Operator ---------------------------------------------------------------------------------- + + requires class User_Operator: public Intra_Operator + { + public: + User_Operator(const unsigned int _number_op); + virtual ~User_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const User_Operator& User_Operator); + + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// StopCondition ----------------------------------------------------------------------------------- + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + +// StopCondition_1 ----------------------------------------------------------------------------------- + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _nb_evolution_steps; + unsigned long _nb_iteration_steps; + unsigned int _population_size; // number of individuals + bool _display_state; + + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _check_asynchronous; + + // selection of parents and offsprings + mutable unsigned int _select_parents; + mutable unsigned int _select_offsprings; + + Rlist<unsigned int> _intra_operators; + Rlist<unsigned int> _inter_operators; + + Operator_Pool& _pool; + + public: + SetUpParams (Operator_Pool& pool); + Operator_Pool& pool() const; + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long nb_evolution_steps() const; + const unsigned int population_size() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int check_asynchronous() const; + + void independent_runs(const unsigned int val); + void nb_evolution_steps(const unsigned long val); + void population_size(const unsigned int val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void check_asynchronous(const unsigned int val); + + // gets the i-th operator of inter-population + const unsigned int inter_operator_index(const unsigned int index) const; + const unsigned int inter_operators_size() const; + + // gets the i-th operator of intra-population + const unsigned int intra_operator_index(const unsigned int index) const; + const unsigned int intra_operators_size() const; + + const unsigned int select_parents() const; + const unsigned int select_offsprings() const; + + void select_parents(const unsigned int val); + void select_offsprings(const unsigned int val); + + void RefreshState(const StateCenter& _sc) const; + void UpdateFromState(const StateCenter& _sc) const; + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_generation; + unsigned long nb_evaluation; + double best_cost; + double global_best_cost; + double average_cost; + double standard_deviation; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + ~Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + }; + +// Population --------------------------------------------------------------------------------- + + provides class Population + { + private: + Rarray<Solution*> _parents; // individuals in population + Rarray<Solution*> _offsprings; // offsprings of current population + Rarray<Solution*> _new_parents; // individuals of previous population + Rarray<struct individual> _fitness_values; + Rarray<struct individual> _fitness_aux; + const SetUpParams& _setup; + unsigned int _upper_cost,_lower_cost; // lower and upper fitness of individuals in population + unsigned int _evaluations; + double _average_cost; + + public: + inline void Evaluate(Solution *s, struct individual & _f); + + Population(const Problem& pbm,const SetUpParams& setup); // crea un array de objetos population; + ~Population(); + + friend ostream& operator<< (ostream& os, const Population& population); + friend istream& operator>> (istream& is, Population& population); + Population& operator= (const Population& pop); + const SetUpParams& setup() const; + const Problem& pbm() const; + void initialize(); + + // Generate a new pool of individuals in population + void evolution(); + + // interchange solutions between island + void interchange(const unsigned long current_generation, NetStream& channel); + + // creates a array with fitness of all individuals in population and its position in the population + void evaluate_parents(); + + // creates a array with fitness of all individuals and offsprings in population and its position in the population + void evaluate_offsprings(); + + // selects parents to creates offsprings + void select_parents(); + + // selects individuals for the new population + void select_offsprings(); + + const Rarray<Solution*>& parents() const; + const Rarray<Solution*>& offsprings() const; + Rarray<struct individual>& fitness_values(); + + unsigned int upper_cost() const; + unsigned int lower_cost() const; + unsigned int evaluations() const; + Solution& solution(const unsigned int index) const; + double fitness(const unsigned int index) const; + + double best_cost() const; + double worst_cost() const; + Solution& best_solution() const; + Solution& worst_solution() const; + double average_cost() const; + double standard_deviation() const; + }; + +// Inter_Operator ( abstract )----------------------------------------------------------- + + provides class Inter_Operator + { + protected: + unsigned int migration_rate; + unsigned int migration_size; + unsigned int migration_selection_1; + unsigned int migration_selection_2; + unsigned int migration_selection_conf_1; + unsigned int migration_selection_conf_2; + + unsigned int _number_operator; + const Direction direction; + + public: + Inter_Operator(const unsigned int _number_op, const Direction dir); + virtual ~Inter_Operator(); + + friend ostream& operator<< (ostream& os, const Inter_Operator& inter); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const=0; + virtual void setup(char line[MAX_BUFFER]); + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Migration: public Inter_Operator ----------------------------------------------------------- + + provides class Migration: public Inter_Operator + { + public: + Migration(const Direction dir); + virtual ~Migration(); + + friend ostream& operator<< (ostream& os, const Migration& migration); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const; + }; + +// Selection --------------------------------------------------------- + + provides class Selection + { + protected: + unsigned int _number_selection; + const Direction direction; + + public: + + Selection(const Direction dir); + Selection(const unsigned int _number_sel, const Direction dir); + virtual ~Selection(); + + friend ostream& operator<< (ostream& os, const Selection& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + unsigned int number_selection() const; + + virtual void setup(char line[MAX_BUFFER]); + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + + }; + +// Selection_Parents --------------------------------------------------------------------------------- + + provides class Selection_Parents: public Selection + { + private: + mutable unsigned int selection_position; + + public: + Selection_Parents(const Direction dir); + virtual ~Selection_Parents(); + + friend ostream& operator<< (ostream& os, const Selection_Parents& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const; + }; + +// Selection_New_Population --------------------------------------------------------------------------- + + provides class Selection_New_Population: public Selection + { + private: + mutable unsigned int selection_position; + mutable int d; + Intra_Operator *diverge; + float r; + + public: + Selection_New_Population(const Direction dir); + virtual ~Selection_New_Population(); + + friend ostream& operator<< (ostream& os, const Selection_New_Population& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const; + + virtual void setup(char line[MAX_BUFFER]); + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Selection_Tournament --------------------------------------------------------------------------------- + + provides class Selection_Tournament: public Selection + { + public: + Selection_Tournament(const Direction dir); + virtual ~Selection_Tournament(); + + friend ostream& operator<< (ostream& os, const Selection_Tournament& sel); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tourment_size,const bool remplace) const; + }; + +// Selection_Roulette_Wheel --------------------------------------------------------------------------------- + + provides class Selection_Roulette_Wheel: public Selection + { + public: + Selection_Roulette_Wheel(const Direction); + virtual ~Selection_Roulette_Wheel(); + + friend ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + }; + +// Selection_Rank --------------------------------------------------------------------------------- + + provides class Selection_Rank: public Selection + { + public: + Selection_Rank(const Direction dir); + Selection_Rank(const unsigned int _number_sel, const Direction dir); + virtual ~Selection_Rank(); + + friend ostream& operator<< (ostream& os, const Selection_Rank& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual void reset(); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const; + }; + +// Selection_Best --------------------------------------------------------------------------------- + + provides class Selection_Best: public Selection_Rank + { + private: + mutable unsigned int selection_best_position; + + public: + Selection_Best(const Direction); + virtual ~Selection_Best(); + + friend ostream& operator<< (ostream& os, const Selection_Best& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Selection_Worst --------------------------------------------------------------------------------- + + provides class Selection_Worst: public Selection_Rank + { + private: + mutable unsigned int selection_worst_position; + + public: + Selection_Worst(const Direction); + virtual ~Selection_Worst(); + + friend ostream& operator<< (ostream& os, const Selection_Worst& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Operator_Pool ------------------------------------------------------------------------- + + // pool with all operators and selections that can be chosen in the setup file + provides class Operator_Pool + { + private: + mutable Rlist<Intra_Operator> _intra_operators; + Rlist<Selection> _selectors; + Rlist<Inter_Operator> _inter_operators; + + public: + Operator_Pool(const Problem& pbm); + ~Operator_Pool(); + + Intra_Operator& intra_operator(const unsigned int index) const; + Rlist<Intra_Operator>& intra_operators() const; + Selection& selector(const unsigned int index) const; + const Rlist<Selection>& selectors() const; + Inter_Operator& inter_operator(const unsigned int index) const; + const Rlist<Inter_Operator>& inter_operators() const; + + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Population current_population; + StateCenter _sc; + + double best_cost; + double worst_cost; + Solution best_solution; + double average_cost; + double standard_deviation; + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_evaluations; + + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_worst_cost; + State_Vble _current_average_cost; + State_Vble _current_standard_deviation; + State_Vble _current_time_spent; + + State_Vble _best_solution_trial; + State_Vble _best_cost_trial; + State_Vble _worst_cost_trial; + State_Vble _iteration_best_found_in_trial; + State_Vble _evaluations_best_found_in_trial; + State_Vble _time_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _evaluations_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _global_worst_cost; + State_Vble _time_best_found; + + State_Vble _crossover_probability; // probability of applying the operator over population + State_Vble _diverge_probability; // probability of applying the operator over population + State_Vble _user_op_probability[MAX_USER_OP]; // probabilities of user operators + State_Vble _migration_rate; + State_Vble _migration_size; + State_Vble _migration_selection_1; + State_Vble _migration_selection_2; + State_Vble _migration_selection_conf_1; + State_Vble _migration_selection_conf_2; + State_Vble _select_parents; + State_Vble _select_offsprings; + State_Vble _parameter_select_new_pop; + + State_Vble _display_state; + + public: + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + + virtual int pid() const; + bool end_trial() const; + void end_trial(bool et); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (const unsigned long int nb_generations) =0; + virtual void run (const Population& pop,const unsigned long int nb_generations) =0; + + //Partial execution + virtual void StartUp()=0; + virtual void StartUp(const Population& pop)=0; + + virtual void DoStep()=0; + + // Statistics handling ---------------------------------------------------------------------- + + Statistics& statistics(); + UserStatistics& userstatistics (); + Population& population(); + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling --------------------------------------------------------------------------- + + void RefreshState(); + void RefreshCfgState(); + void UpdateFromState(); + void UpdateFromCfgState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + unsigned long current_evaluations() const; + Solution current_best_solution() const; + double current_best_cost() const; + double current_worst_cost() const; + double current_average_cost() const; + double current_standard_deviation() const; + float current_time_spent() const; + Solution best_solution_trial() const; + double best_cost_trial() const; + double worst_cost_trial() const; + unsigned int iteration_best_found_in_trial() const; + unsigned int evaluations_best_found_in_trial() const; + float time_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + unsigned int evaluations_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + double global_worst_cost() const; + float time_best_found() const; + int display_state() const; + + float *crossover_probability() const; + float *diverge_probability() const; + float *user_op_probability(const int index) const; + unsigned int migration_rate() const; + unsigned int migration_size() const; + unsigned int migration_selection_1() const; + unsigned int migration_selection_2() const; + unsigned int migration_selection_conf_1() const; + unsigned int migration_selection_conf_2() const; + unsigned int select_parents() const; + unsigned int select_offprings() const; + float parameter_select_new_pop() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_evaluations(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_worst_cost(const double value); + void current_average_cost(const double value); + void current_standard_deviation(const double value); + void current_time_spent(const float value); + void best_solution_trial(const Solution& sol); + void best_cost_trial(const double value); + void worst_cost_trial(const double value); + void iteration_best_found_in_trial(const unsigned int value); + void evaluations_best_found_in_trial(const unsigned int value); + void time_best_found_trial(const float value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void evaluations_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void global_worst_cost(const double value); + void time_best_found(const float value); + void display_state(const int value); + + void crossover_probability(const float *probability); + void diverge_probability(const float *probability); + void user_op_probability(const int index,const float *probability); + void migration_rate(const unsigned int rate); + void migration_size(const unsigned int size); + void migration_selection_1(const unsigned int seleciton_1); + void migration_selection_2(const unsigned int selection_2); + void migration_selection_conf_1(const unsigned int selection_conf_1); + void migration_selection_conf_2(const unsigned int selection_conf_2); + void select_parents(const unsigned int selection); + void select_offsprings(const unsigned int selection); + void parameter_select_new_pop(const float value); + + void KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_trial,const float total_time_spent); + + void show_state() const; + }; + + provides class Solver_Seq: public Solver + { + public: + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state(); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + int acum_evaluations; + int acum_iterations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state(); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + int acum_evaluations; + int acum_iterations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + void reset(); + }; + +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.cc b/ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.cc new file mode 100644 index 0000000..65672fd --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.cc @@ -0,0 +1,3033 @@ +#include "CHC.hh" + +skeleton CHC +{ +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (Operator_Pool& pool) + : _independent_runs(0), + _nb_evolution_steps(0), + _population_size(0), + _select_parents(6), // Selection of parents: Select all individuals. (fixed) + _select_offsprings(7), // Selection of offspring : Select the best individuals. (fixed) + _inter_operators(), + _intra_operators(), + _refresh_global_state(1), + _synchronized(0), + _check_asynchronous(1), + _display_state(0), + _pool(pool) + {} + + Operator_Pool& SetUpParams::pool() const + { + return _pool; + } + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + long op; + int parameter; + short int nb_section=0; + short int nb_io = 0; + short int nb_param=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"Selection-Parameters"))) nb_section=1; + if (!(strcmp(command,"Intra-Operators"))) nb_section=2; + if (!(strcmp(command,"Inter-Operators"))) nb_section=3; + if (!(strcmp(command,"LAN-configuration"))) nb_section=4; + + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.nb_evolution_steps(op); break; + case 2: setup.population_size(op); break; + case 3: setup.display_state(op); break; + } + nb_param++; + break; + case 1: setup.pool().selector(setup.select_offsprings()).setup(buffer); + break; + case 2: setup.pool().intra_operators().append(Intra_Operator::create(op)); + setup.pool().intra_operator(nb_io).setup(buffer); + setup._intra_operators.append(new unsigned int(nb_io)); + nb_io++; + break; + case 3: setup._inter_operators.append(new unsigned int(op)); + setup.pool().inter_operator(op).setup(buffer); + break; + case 4: if (nb_LAN_param>=3) break; + switch (nb_LAN_param) + { + case 0: setup.refresh_global_state(op); break; + case 1: setup.synchronized(op); break; + case 2: assert(op>0); + setup.check_asynchronous(op); break; + } + nb_LAN_param++; + break; + } + } + + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evolution steps: " << setup.nb_evolution_steps() << endl + << "\t" << "Size of Population: " << setup.population_size() << endl; + os << "\t" <<"With combination between parents and offsprings" << endl; + + os << "\t" << "Display State: " << setup.display_state() << endl << endl + << "\t" << "Selections:" << endl + << "\t" << "-----------" << endl << endl + << "\t" << "Selection parents -> " << setup.pool().selector(setup.select_parents()) << endl + << "\t" << "Selection offsprings -> " << setup.pool().selector(setup.select_offsprings()) << endl + << "\t" << "Intra_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.intra_operators_size();i++) + os << "\t" << (setup.pool().intra_operator(setup.intra_operator_index(i))) << endl; + + os << endl << "\t" << "Inter_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.inter_operators_size();i++) + os << "\t" << "Operator: " << setup.pool().inter_operator(setup.inter_operator_index(i)) << endl; + + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + os << "\t" << "Interval for checking asynchronous receptions: " << setup.check_asynchronous() << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + continue_question(); + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::nb_evolution_steps() const + { + return _nb_evolution_steps; + } + + const unsigned int SetUpParams::population_size() const + { + return _population_size; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::check_asynchronous() const + { + return _check_asynchronous; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs=val; + } + + void SetUpParams::nb_evolution_steps(const unsigned long val) + { + _nb_evolution_steps=val; + } + + void SetUpParams::population_size(const unsigned int val) + { + _population_size=val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::check_asynchronous(const unsigned int val) + { + _check_asynchronous=val; + } + + const unsigned int SetUpParams::select_parents() const + { + return _select_parents; + } + + const unsigned int SetUpParams::select_offsprings() const + { + return _select_offsprings; + } + + void SetUpParams::select_parents(const unsigned int val) + { + _select_parents=val; + } + + void SetUpParams::select_offsprings(const unsigned int val) + { + _select_offsprings=val; + } + + const unsigned int SetUpParams::intra_operator_index(const unsigned int index) const + { + return _intra_operators[index]; + } + + const unsigned int SetUpParams::intra_operators_size() const + { + return _intra_operators.size(); + } + + const unsigned int SetUpParams::inter_operator_index(const unsigned int index) const + { + return _inter_operators[index]; + } + + const unsigned int SetUpParams::inter_operators_size() const + { + return _inter_operators.size(); + } + + void SetUpParams::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_select_parents",(char *)&_select_parents,1,sizeof(_select_parents)); + _sc.set_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,1,sizeof(_select_offsprings)); + _sc.set_contents_state_variable("_display_state",(char *)&_display_state,1,sizeof(bool)); + } + + void SetUpParams::UpdateFromState(const StateCenter& _sc) const + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_select_parents",(char *)&_select_parents,nbytes,length); + _sc.get_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_display_state",(char *)&_display_state,nbytes,length); + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Trial: " << stats.stats_data[i].trial + << " Generation: " << stats.stats_data[i].nb_generation + << " Evaluation: " << stats.stats_data[i].nb_evaluation + << " Current best cost: " << stats.stats_data[i].best_cost + << " Global best cost: " << stats.stats_data[i].global_best_cost + << " Avg: " << stats.stats_data[i].average_cost + << " Std. Dev.: " << stats.stats_data[i].standard_deviation; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + struct stat *new_stat=(struct stat *)malloc(sizeof(struct stat)); + + new_stat->trial=solver.current_trial(); + new_stat->nb_generation=solver.current_iteration(); + new_stat->nb_evaluation=solver.current_evaluations(); + new_stat->average_cost=solver.current_average_cost(); + new_stat->standard_deviation=solver.current_standard_deviation(); + new_stat->best_cost=solver.current_best_cost(); + new_stat->global_best_cost=solver.global_best_cost(); + + stats_data.append(*new_stat); + } + + void Statistics::clear() + { + stats_data.remove(); + } + + Statistics::~Statistics() + {} + +// Population ------------------------------------------------------ + + Population::Population(const Problem& pbm,const SetUpParams& setup) + :_parents(setup.population_size()), + _fitness_values(setup.population_size()), + _new_parents(setup.population_size()), + _offsprings(setup.population_size()), + _setup(setup), + _evaluations(0) + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]=new Solution(pbm); + _new_parents[i]=new Solution(pbm); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + for (int i=0;i<_offsprings.size();i++) + _offsprings[i]=new Solution(pbm); + + } + + void Population::Evaluate(Solution* sols,struct individual &_f) + { + if(_f.change) + { + _f.change = false; + _f.fitness = sols->fitness(); + _evaluations++; + } + } + + Population& Population::operator= (const Population& pop) + { + for (int i=0;i<_parents.size();i++) + { + *_parents[i]=*((pop.parents())[i]); + _fitness_values[i] = pop._fitness_values[i]; + _evaluations = pop._evaluations; + } + return (*this); + } + + istream& operator>> (istream& is, Population& population) + { + return is; + } + + ostream& operator<< (ostream& os, const Population& population) + { + os << "---------------------------------------------------------------" << endl; + os << " PRESENT POPULATION " << endl << endl; + for (int i=0;i<population._parents.size();i++) + os << *population._parents[i] << endl; + os << endl << "---------------------------------------------------------------" << endl; + return os; + } + + const SetUpParams& Population::setup() const + { + return _setup; + } + + void Population::initialize() + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]->initialize(); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + evaluate_parents(); + } + + void Population::evaluate_parents() + { + double upper_fitness=(infinity() * (-1)); + double lower_fitness=(infinity()); + double current_fitness; + double cost=0.0; + + for (int i=0;i<_fitness_values.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + current_fitness = _fitness_values[i].fitness; + + if (current_fitness > upper_fitness ) + { + _upper_cost=i; + upper_fitness = current_fitness; + } + + if (current_fitness < lower_fitness ) + { + _lower_cost=i; + lower_fitness = current_fitness; + } + + cost += current_fitness; + } + + _average_cost = cost / _fitness_values.size(); + } + + void Population::evaluate_offsprings() + { + int i=0; + + _fitness_aux=Rarray<struct individual>(_parents.size() + _offsprings.size()); + for (i=0;i<_parents.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + _fitness_aux[i] = _fitness_values[i]; + } + + for (int j=i;(j-i)<_offsprings.size();j++) + { + _fitness_aux[j].index=j; + _fitness_aux[j].change=true; + Evaluate(_offsprings[j-i],_fitness_aux[j]); + } + } + + void Population::evolution() + { + select_parents(); // selects individuals to apply operators + + // apply selected operators + for (int i=0;i<_setup.intra_operators_size();i++) + _setup.pool().intra_operator(_setup.intra_operator_index(i)).execute(_offsprings); + + evaluate_offsprings(); + select_offsprings(); // selects new individuals + evaluate_parents(); // calculates fitness of new individuals + } + + void Population::interchange(const unsigned long current_generation, NetStream& channel) + { + // apply selected operators + for (int i=0;i<_setup.inter_operators_size();i++) + _setup.pool().inter_operator(_setup.inter_operator_index(i)).execute((*this),current_generation,channel,_setup.synchronized(),_setup.check_asynchronous()); + } + + void Population::select_parents() + { + _setup.pool().selector(_setup.select_parents()).prepare(_fitness_values,false); + struct individual ind; + for (int i=0;i<_offsprings.size();i++) + { + ind = _setup.pool().selector(_setup.select_parents()).select_one(_parents,_offsprings,_fitness_values,0,false); + *_offsprings[i] = *_parents[ind.index]; + } + } + + void Population::select_offsprings() + { + _setup.pool().selector(_setup.select_offsprings()).prepare(_fitness_aux,false); + const int ps = _parents.size(); + Rarray<struct individual> aux(ps); + + for (int i=0;i<ps;i++) + { + aux[i] = _setup.pool().selector(_setup.select_offsprings()).select_one(_parents,_offsprings,_fitness_aux,0,false); + if(aux[i].index < ps) + { + *_new_parents[i] = *_parents[aux[i].index]; + aux[i].index = i; + } + else + { + *_new_parents[i] = *_offsprings[aux[i].index-ps]; + aux[i].index = i; + } + } + + Solution *interchange; + for (int i=0;i<ps;i++) + { + interchange=_parents[i]; + _parents[i]=_new_parents[i]; // interchanges pointers to solutions ( NO solutions !! ) + _new_parents[i]=interchange; + } + + for (int i=0;i<ps;i++) + { + _fitness_values[i] = aux[i]; + } + } + + const Rarray<Solution*>& Population::parents() const + { + return _parents; + } + + const Rarray<Solution*>& Population::offsprings() const + { + return _offsprings; + } + + Rarray<struct individual>& Population::fitness_values() + { + return _fitness_values; + } + + unsigned int Population::upper_cost() const + { + return _upper_cost; + } + + unsigned int Population::lower_cost() const + { + return _lower_cost; + } + + unsigned int Population::evaluations() const + { + return _evaluations; + } + + double Population::best_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_lower_cost].fitness; + else + return _fitness_values[_upper_cost].fitness; + } + + double Population::worst_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_upper_cost].fitness; + else + return _fitness_values[_lower_cost].fitness; + } + + Solution& Population::best_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_lower_cost].index]; + else + return *_parents[_fitness_values[_upper_cost].index]; + } + + Solution& Population::worst_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_upper_cost].index]; + else + return *_parents[_fitness_values[_lower_cost].index]; + } + + Solution& Population::solution(const unsigned int index) const + { + return *_parents[index]; + } + + double Population::fitness(const unsigned int index) const + { + return _fitness_values[index].fitness; + } + + double Population::average_cost() const + { + return _average_cost; + } + + double Population::standard_deviation() const + { + double standard=0.0; + for (int i=0;i<_fitness_values.size();i++) + standard += pow ((_fitness_values[i].fitness - _average_cost),2); + standard=sqrt(standard / (_fitness_values.size()-1)); + return standard; + } + + Population::~Population() + { + for (int i=0;i<_parents.size();i++) + delete(_parents[i]); + for (int i=0;i<_offsprings.size();i++) + delete(_offsprings[i]); + for (int j=0;j<_new_parents.size();j++) + delete(_new_parents[j]); + } + +// Intra_operator -------------------------------------------------------------- + + Intra_Operator::Intra_Operator(const unsigned int _number_op):_number_operator(_number_op),probability(NULL) + {} + + unsigned int Intra_Operator::number_operator() const + { + return _number_operator; + } + + Intra_Operator *Intra_Operator::create(unsigned int _number_op) + { + switch (_number_op) + { + case 0: return new Crossover();break; + case 1: return new Diverge();break; + default: return User_Operator::create(_number_op); break; + } + } + + ostream& operator<< (ostream& os, const Intra_Operator& intra) + { + switch (intra.number_operator()) + { + case 0: os << (Crossover&)intra;break; + case 1: os << (Diverge&)intra;break; + default: os << (User_Operator&)intra;break; + } + return os; + } + + Intra_Operator::~Intra_Operator() + {} + +// Crossover:Intra_operator ------------------------------------------------------------- + + Crossover::Crossover():Intra_Operator(0) + { + probability = new float[1]; + probability[0] = -1.0; + } + + void Crossover::cross(Solution& sol1,Solution& sol2) const // dadas dos soluciones de la poblacion, las cruza + { + int dh = 0; + + if(probability[0] <= 0.0) + { + probability[0] = sol1.lengthInBits()/4; + } + + for(int i = 0; i < sol1.lengthInBits();i++) + if(!sol1.equalb(i,sol2)) dh++; + + if((dh/2) > probability[0]) + { + for(int i = 0; i < sol1.lengthInBits();i++) + if((!sol1.equalb(i,sol2)) && (0.5 <= rand01())) + { + sol1.swap(i,sol2); + } + } + else + { + sol1.invalid(); + sol2.invalid(); + } + } + + void Crossover::execute(Rarray<Solution*>& sols) const + { + for(int i=0;i+1<sols.size();i=i+2) + cross(*sols[i],*sols[i+1]); + } + + ostream& operator<< (ostream& os, const Crossover& cross) + { + os << "Crossover."; + return os; + } + + void Crossover::RefreshState(const StateCenter& _sc) const + {} + + void Crossover::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)probability,nbytes,length); + } + + void Crossover::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d ",&op); + } + + Crossover::~Crossover() + { + delete [] probability; + } + + +// Diverge: Sub_operator ------------------------------------------------------------- + + Diverge::Diverge():Intra_Operator(1) + { + probability = new float[1]; + } + + void Diverge::diverge(Solution& sol) const + { + for(int i = 0; i < sol.lengthInBits(); i++) + if(rand01() < probability[0]) sol.flip(i); + } + + void Diverge::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i<sols.size();i++) + diverge(*sols[i]); + } + + ostream& operator<< (ostream& os, const Diverge& diverge) + { + os << "Diverge." << " Probability: " << diverge.probability[0]; + return os; + } + + void Diverge::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f ",&op,&probability[0]); + assert(probability[0]>=0); + } + + void Diverge::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_diverge_probability",(char *)probability,1,sizeof(float)); + } + + void Diverge::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_diverge_probability",(char *)probability,nbytes,length); + } + + Diverge::~Diverge() + { + delete [] probability; + } + + +// Inter_operator ------------------------------------------------------------------- + + Inter_Operator::Inter_Operator(const unsigned int _number_op,const Direction dir): + _number_operator(_number_op), + direction(dir), + migration_rate(1), + migration_size(1), + migration_selection_1(0), + migration_selection_2(0), + migration_selection_conf_1(0), + migration_selection_conf_2(0) + {} + + unsigned int Inter_Operator::number_operator() const + { + return _number_operator; + } + + void Inter_Operator::setup(char line[MAX_BUFFER]) + { + int op; + int new_migration_rate=1; + int new_migration_size=1; + int new_migration_selection_1=0; + int new_migration_selection_conf_1=0; + int new_migration_selection_2=0; + int new_migration_selection_conf_2=0; + + sscanf(line," %d %d %d %d %d %d %d ",&op,&new_migration_rate,&new_migration_size,&new_migration_selection_1,&new_migration_selection_conf_1,&new_migration_selection_2,&new_migration_selection_conf_2); + + assert(new_migration_rate>0); + assert(new_migration_size>0); + assert(new_migration_selection_1>=0); + assert(new_migration_selection_conf_1>=0); + assert(new_migration_selection_2>=0); + assert(new_migration_selection_conf_2>=0); + + migration_rate=new_migration_rate; + migration_size=new_migration_size; + migration_selection_1=new_migration_selection_1; + migration_selection_conf_1=new_migration_selection_conf_1; + migration_selection_2=new_migration_selection_2; + migration_selection_conf_2=new_migration_selection_conf_2; + } + + void Inter_Operator::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_migration_rate",(char *)&migration_rate,1,sizeof(migration_rate)); + _sc.set_contents_state_variable("_migration_size",(char *)&migration_size,1,sizeof(migration_size)); + _sc.set_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,1,sizeof(migration_selection_1)); + _sc.set_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,1,sizeof(migration_selection_2)); + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,1,sizeof(migration_selection_conf_1)); + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,1,sizeof(migration_selection_conf_2)); + } + + void Inter_Operator::UpdateFromState(const StateCenter& _sc) + { + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&migration_rate,nitems,length); + _sc.get_contents_state_variable("_migration_size",(char *)&migration_size,nitems,length); + _sc.get_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,nitems,length); + } + + ostream& operator<< (ostream& os, const Inter_Operator& inter) + { + switch (inter.number_operator()) + { + case 0: os << (Migration&)inter;break; + } + return os; + } + + Inter_Operator::~Inter_Operator() + {} + +// Migration ------------------------------------------------------------ + + Migration::Migration(const Direction dir):Inter_Operator(0,dir) + {} + + void Migration::execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asynchronous) const + { + + Solution* solution_to_send; + Solution* solution_received; + Solution* solution_to_remplace; + bool need_to_revaluate=false; + int mypid; + + int nb_proc=_netstream.pnumber(); // Get the number of processes running + + mypid=_netstream.my_pid(); + + int to = (mypid + 1) % nb_proc; // Source (from) and Target (to) of processes + int from = (nb_proc + mypid - 1) % nb_proc; + + // process number 0 is only to store the global state + if (to==0) to=1; + if (from==0) from=nb_proc - 1; + + _netstream << set_target(to) << set_source(from) + << get_target(&to) << get_source(&from); + + if ( (current_generation % migration_rate) == 0 + && (current_generation!=pop.setup().nb_evolution_steps())) // in this generation this operator have to be applied + { + pop.setup().pool().selector(migration_selection_1).prepare(pop.fitness_values(),false); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to send + solution_to_send = pop.parents()[pop.setup().pool().selector(migration_selection_1).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_1,false).index]; + + _netstream << *solution_to_send; + } + _netstream << pack_end; + + if (synchronized) // synchronous mode: blocked until data are received + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << set_source(MPI_ANY_SOURCE); + int tipo = 0; + _netstream._wait2(any,tipo); + + if (tipo == 1){ + return; + } + + _netstream << wait(packed); + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } + _netstream << pack_end; + + } + } // end if + + if (!synchronized && ((current_generation % check_asynchronous) ==0)) + { // asynchronous mode: if there are not data, continue; + // but, if there are data, i have to receive it + int pending=false; + _netstream._probe(packed,pending); + if (pending) + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + pending=false; + _netstream._probe(regular,pending); + if (!pending) break; + + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } // end for + _netstream << pack_begin; + } // end if + } + + if (need_to_revaluate) pop.evaluate_parents(); + } + + ostream& operator<< (ostream& os, const Migration& migration) + { + os << "Migration." + << endl << "\t" << " Rate: " << migration.migration_rate + << endl << "\t" << " Size: " << migration.migration_size + << endl << "\t" << " Selection 1: " << migration.migration_selection_1 + << endl << "\t" << " Selection 1 Parameter: " << migration.migration_selection_conf_1 + << endl << "\t" << " Selection 2: " << migration.migration_selection_2 + << endl << "\t" << " Selection 2 Parameter: " << migration.migration_selection_conf_2; + return os; + } + + Migration::~Migration() + {} + +// Selection ------------------------------------------------------------ + + Selection::Selection(const Direction dir):_number_selection(0),direction(dir) + {} + + Selection::Selection(const unsigned int _number_sel, const Direction dir):_number_selection(_number_sel),direction(dir) + {} + + void Selection::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + {} + + struct individual Selection::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const + { // select a random individual + return fitness_values[rand_int(0,fitness_values.size()-1)]; + } + + unsigned int Selection::number_selection() const + { + return _number_selection; + } + + ostream& operator<< (ostream& os, const Selection& sel) + { + switch (sel.number_selection()) + { + case 0: os << "Random Selection"; break; + case 1: os << (Selection_Tournament&)sel; break; + case 2: os << (Selection_Roulette_Wheel&)sel; break; + case 3: os << (Selection_Rank&)sel; break; + case 4: os << (Selection_Best&)sel; break; + case 5: os << (Selection_Worst&)sel; break; + case 6: os << (Selection_Parents&)sel; break; + case 7: os << (Selection_New_Population&)sel; break; + } + return os; + } + + void Selection::setup(char line[MAX_BUFFER]) + {} + + void Selection::RefreshState(const StateCenter& _sc) const + {} + + void Selection::UpdateFromState(const StateCenter& _sc) + {} + + + Selection::~Selection() + {} + +// Selection_Tournament---------------------------------------------------- + + Selection_Tournament::Selection_Tournament(const Direction dir):Selection(1,dir) + {} + + struct individual Selection_Tournament::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tournament_size, const bool remplace) const + { + unsigned int best_sol=0; + double best_fitness=((-1) * direction * infinity()); + unsigned int index; + + if (remplace) best_fitness = -1 * best_fitness; + + unsigned int new_tournament_size=tournament_size; + if (tournament_size==0) new_tournament_size=1; + + for (int i=0;i<new_tournament_size;i++) + { + index=rand_int(0,fitness_values.size()-1); + + switch (direction) + { + case (minimize): if (((!remplace) && (fitness_values[index].fitness<best_fitness)) + || ((remplace) && (fitness_values[index].fitness>best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + case (maximize): if (((!remplace) && (fitness_values[index].fitness>best_fitness)) + || ((remplace) && (fitness_values[index].fitness<best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + } + } + + return fitness_values[best_sol]; + } + + ostream& operator<< (ostream& os, const Selection_Tournament& sel) + { + os << "Tournament Selection."; + return os; + } + + Selection_Tournament::~Selection_Tournament() + {} + +// Selection_Roulette_Wheel --------------------------------------------------- + + Selection_Roulette_Wheel::Selection_Roulette_Wheel(const Direction dir):Selection(2,dir) + {} + + void Selection_Roulette_Wheel::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + + double overall_fitness=0.0; + + // inverts fitness values to select less fitness individuals with a high probability + if ((direction==maximize && (remplace)) || ((direction==minimize) && (!(remplace)))) + { + // fitness assigned if the fitness value is 0 in this case + double value_if_zero=DBL_MAX; + unsigned int nb_zeros=0; + + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + value_if_zero-=fitness_values[i].fitness; + else + nb_zeros++; + } + + value_if_zero=value_if_zero/nb_zeros; + + // Warning !! if fitness is 0 (1/0 ?) + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + fitness_values[i].sel_parameter = (1 / fitness_values[i].fitness ); + else + fitness_values[i].sel_parameter = value_if_zero; + overall_fitness+= fitness_values[i].sel_parameter; + } + } + else + { + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = fitness_values[i].fitness; + overall_fitness+= fitness_values[i].sel_parameter; + } + + } + + if (overall_fitness>DBL_MAX) overall_fitness=DBL_MAX; + + // calculate relative fitness + double previous=0.0; + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = (fitness_values[i].sel_parameter / overall_fitness) + previous; + previous = fitness_values[i].sel_parameter; + } + } + + struct individual Selection_Roulette_Wheel::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy, const bool remplace) const + { + double random_selected=rand01(); + int i=0; + + while (random_selected > fitness_values[i].sel_parameter ) + i++; + + return fitness_values[i]; + } + + ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel) + { + os << "Roulette Wheel Selection."; + return os; + } + + Selection_Roulette_Wheel::~Selection_Roulette_Wheel() + {} + +// Selection_Rank -------------------------------------------------- + + int lessF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness < i2.fitness; + } + + int greaterF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness > i2.fitness; + } + + Selection_Rank::Selection_Rank(const Direction dir):Selection(3,dir) + {} + + Selection_Rank::Selection_Rank(const unsigned int _number_sel, const Direction dir):Selection(_number_sel,dir) + {} + + void Selection_Rank::reset() + {} + + void Selection_Rank::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + reset(); + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(lessF); + else + fitness_values.sort(greaterF); + } + + struct individual Selection_Rank::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const + { + + unsigned int new_portion=portion; + if (portion==0 || portion>100) new_portion=100; + + return fitness_values[rand_int(0,(( fitness_values.size() * new_portion )/ 100)-1)]; + } + + ostream& operator<< (ostream& os, const Selection_Rank& sel) + { + os << "Rank-Ordered Selection."; + return os; + } + + Selection_Rank::~Selection_Rank() + {} + +// Selection_Best -------------------------------------------------- + + Selection_Best::Selection_Best(const Direction dir):Selection_Rank(4,dir),selection_best_position(0) + {} + + struct individual Selection_Best::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_best_position; + selection_best_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + return fitness_values[position_to_return]; + } + + void Selection_Best::reset() + { + selection_best_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Best& sel) + { + os << "Selection of best ordered individuals."; + return os; + } + + Selection_Best::~Selection_Best() + {} + +// Selection_Worst -------------------------------------------------- + + Selection_Worst::Selection_Worst(const Direction dir):Selection_Rank(5,dir),selection_worst_position(0) + {} + + struct individual Selection_Worst::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_worst_position; + selection_worst_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + int index=(fitness_values.size()-1) - position_to_return; + return fitness_values[index]; + } + + void Selection_Worst::reset() + { + selection_worst_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Worst& sel) + { + os << "Selection of worst ordered individuals."; + return os; + } + + Selection_Worst::~Selection_Worst() + {} + +// Selection_Parents --------------------------------------------------------------------------------- + + Selection_Parents::Selection_Parents(const Direction dir):Selection(6,dir),selection_position(0) + {} + + Selection_Parents::~Selection_Parents() + {} + + ostream& operator<< (ostream& os, const Selection_Parents& sel) + { + os << "CHC Selection: Parents Selection."; + return os; + } + + void Selection_Parents::prepare(Rarray<struct individual>& fitness_values,const bool remplace) // const + { + selection_position = 0; + int limit1,limit2; + register int max = fitness_values.size(); + + struct individual interchange; + + for (int i=0;i<max*3;i++) + { + limit1 = rand_int(0,max-1); + limit2 = rand_int(0,max-1); + interchange=fitness_values[limit1]; + fitness_values[limit1]=fitness_values[limit2]; + fitness_values[limit2]=interchange; + } + } + + struct individual Selection_Parents::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const + { + int index = selection_position; + selection_position++; + + index = index % fitness_values.size(); + + return fitness_values[index]; + } + +// Selection_New_Population --------------------------------------------------------------------------- + + Selection_New_Population::Selection_New_Population(const Direction dir) + :Selection(7,dir) + ,diverge(NULL) + ,d(-1) + {} + + Selection_New_Population::~Selection_New_Population() + { + if(diverge != NULL) delete diverge; + } + + ostream& operator<< (ostream& os, const Selection_New_Population& sel) + { + os << "CHC Selection: New Population Selection." << " Diverge Operator: " << *sel.diverge; + return os; + } + + + void Selection_New_Population::prepare(Rarray<struct individual>& fitness_values,const bool remplace) // const + { + selection_position = 0; + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(greaterF); + else + fitness_values.sort(lessF); + } + + struct individual Selection_New_Population::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int param,const bool remplace) const + { + bool change = false; + if(d == -1) d = to_select_1[0]->lengthInBits() / 4; + + if(selection_position == 0) + { + for(int i= 0; i < to_select_1.size(); i++) + if(fitness_values[i].index > (to_select_1.size()-1)) change = true; + if(change) selection_position++; + else selection_position--; + } + + if(selection_position == -1) + { + d--; + if(d < 0) + { + selection_position--; + d = (int) (r * (1.0-r) * to_select_1[0]->lengthInBits()); + } + else selection_position = 1; + } + + if(selection_position == -2) + { + assert(diverge != NULL); + for(int i = 1; i < to_select_1.size(); i++) + { + if(rand01() < r) ((Diverge *)diverge)->diverge(*to_select_1[i]); + } + for(int i= 0; i < fitness_values.size(); i++) + if(fitness_values[i].index < (to_select_1.size()-1)) fitness_values[i].change = true; + + selection_position = 1; + } + + if(selection_position > 0) + { + int index = selection_position-1; + selection_position++; + return fitness_values[index]; + } + } + + void Selection_New_Population::setup(char line[MAX_BUFFER]) + { + int div; + float div_par; + + sscanf(line," %f %d %f ",&r,&div, &div_par); + assert(r>=0); + + sprintf(line,"%d %f ",div,div_par); + + diverge = Intra_Operator::create(div); + assert(diverge != NULL); + + diverge->setup(line); + } + + void Selection_New_Population::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_parameter_select_new_pop",(char *)&r,1,sizeof(float)); + } + + void Selection_New_Population::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)&r,nbytes,length); + } + +// Operator_Pool ------------------------------------------------------------------------ + + Operator_Pool::Operator_Pool(const Problem& pbm) + { + // introduces all operators and selections in lists + + // Index to be chosen in setup file + //------------------------------------- + // The Intra_Operators are introduced dimanicly in setup + + _selectors.append(new Selection(pbm.direction())); // 0 + _selectors.append(new Selection_Tournament(pbm.direction())); // 1 + _selectors.append(new Selection_Roulette_Wheel(pbm.direction())); // 2 + _selectors.append(new Selection_Rank(pbm.direction())); // 3 + _selectors.append(new Selection_Best(pbm.direction())); // 4 + _selectors.append(new Selection_Worst(pbm.direction())); // 5 + _selectors.append(new Selection_Parents(pbm.direction())); // 6 + _selectors.append(new Selection_New_Population(pbm.direction())); // 7 + + _inter_operators.append(new Migration(pbm.direction())); // 0 + } + + Intra_Operator& Operator_Pool::intra_operator(const unsigned int index) const + { + assert(index < _intra_operators.size()); + return _intra_operators[index]; + } + + Rlist<Intra_Operator>& Operator_Pool::intra_operators() const + { + return _intra_operators; + } + + Selection& Operator_Pool::selector(const unsigned int index) const + { + assert(index < _selectors.size()); + return _selectors[index]; + } + + const Rlist<Selection>& Operator_Pool::selectors() const + { + return _selectors; + } + + Inter_Operator& Operator_Pool::inter_operator(const unsigned int index) const + { + assert(index < _inter_operators.size()); + return _inter_operators[index]; + } + + const Rlist<Inter_Operator>& Operator_Pool::inter_operators() const + { + return _inter_operators; + } + + Operator_Pool::~Operator_Pool() + {} + +// Solver (superclasse)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + current_population(pbm,setup), + best_cost((-1) * pbm.direction() * infinity()), + worst_cost((-1) * best_cost), + best_solution(problem), + average_cost(0.0), + standard_deviation(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_evaluations("_current_evaluations",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_worst_cost("_current_worst_cost",_sc), + _current_average_cost("_current_average_cost",_sc), + _current_standard_deviation("_current_standard_deviation",_sc), + _current_time_spent("_current_time_spent",_sc), + _best_solution_trial("_best_sol_trial",_sc), + _best_cost_trial("_best_cost_trial",_sc), + _worst_cost_trial("_worst_cost_trial",_sc), + _iteration_best_found_in_trial("_iteration_best_found_in_trial",_sc), + _evaluations_best_found_in_trial("_evaluations_best_found_in_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found",_sc), + _evaluations_best_found("_evaluations_best_found",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _global_worst_cost("_global_worst_cost",_sc), + _time_best_found("_time_best_found",_sc), + _crossover_probability("_crossover_probability",_sc), + _diverge_probability("_diverge_probability",_sc), + _migration_rate("_migration_rate",_sc), + _migration_size("_migration_size",_sc), + _migration_selection_1("_migration_selection_1",_sc), + _migration_selection_2("_migration_selection_2",_sc), + _migration_selection_conf_1("_migration_selection_conf_1",_sc), + _migration_selection_conf_2("_migration_selection_conf_2",_sc), + _select_parents("_select_parents",_sc), + _select_offsprings("_select_offsprings",_sc), + _parameter_select_new_pop("_parameter_select_new_pop",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_evaluations(0); + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + best_solution_trial(best_solution); + best_cost_trial(best_cost); + worst_cost_trial(worst_cost); + iteration_best_found_in_trial(0); + evaluations_best_found_in_trial(0); + time_best_found_trial(time_spent_in_trial); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + evaluations_best_found(0); + global_best_solution(best_solution); + global_best_cost(best_cost); + global_worst_cost(worst_cost); + time_best_found(total_time_spent); + + float prob[MAX_PROB_PER_OP] = {0.0}; + crossover_probability(prob); + diverge_probability(prob); + + char aux[] = "_user_op_probability"; + char nombre[30]; + for(int i = 0; i < MAX_USER_OP; i++) + { + sprintf(nombre,"%s%d",aux,i); + _user_op_probability[i].set_name((char *)nombre); + _sc.add(_user_op_probability[i]); + user_op_probability(i,prob); + } + + migration_rate(0); + migration_size(0); + migration_selection_1(0); + migration_selection_2(0); + migration_selection_conf_1(0); + migration_selection_conf_2(0); + select_parents(0); + select_offsprings(0); + parameter_select_new_pop(0.0); + display_state(setup.display_state()); + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + void Solver::end_trial(bool et) + { + _end_trial = et; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _current_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_iteration.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_evaluations() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_evaluations.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _current_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_average_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_average_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_standard_deviation() const + { + double value=0.0; + unsigned long nitems,length; + _current_standard_deviation.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::best_solution_trial() const + { + Solution sol(problem); + char data_stored[_best_solution_trial.get_nitems() + _best_solution_trial.get_length()]; + unsigned long nitems,length; + _best_solution_trial.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::best_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _best_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::worst_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _worst_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _global_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::global_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _display_state.get_contents((char *)&value, nitems, length); + return value; + } + + float *Solver::crossover_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::diverge_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_diverge_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::user_op_probability(const int index) const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.get_contents_state_variable(aux,(char *)¤t_probability,nitems,length); + return current_probability; + } + + unsigned int Solver::migration_rate() const + { + unsigned int rate=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&rate,nitems,length); + return rate; + } + + unsigned int Solver::migration_size() const + { + unsigned int size=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_size",(char *)&size,nitems,length); + return size; + } + + unsigned int Solver::migration_selection_1() const + { + unsigned int selection_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_1",(char *)&selection_1,nitems,length); + return selection_1; + } + + unsigned int Solver::migration_selection_2() const + { + unsigned int selection_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_2",(char *)&selection_2,nitems,length); + return selection_2; + } + + unsigned int Solver::migration_selection_conf_1() const + { + unsigned int selection_conf_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,nitems,length); + return selection_conf_1; + } + + unsigned int Solver::migration_selection_conf_2() const + { + unsigned int selection_conf_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,nitems,length); + return selection_conf_2; + } + + unsigned int Solver::select_parents() const + { + unsigned int select_parents=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_parents",(char *)&select_parents,nitems,length); + return select_parents; + } + + unsigned int Solver::select_offprings() const + { + unsigned int select_offsprings=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_offsprings",(char *)&select_offsprings,nitems,length); + return select_offsprings; + } + + float Solver::parameter_select_new_pop() const + { + float parameter_select_new_pop; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_new_pop",(char *)¶meter_select_new_pop,nitems,length); + return parameter_select_new_pop; + } + + void Solver::current_trial(const unsigned int value) + { + _current_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _current_iteration.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_evaluations(const unsigned long value) + { + _current_evaluations.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _current_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _current_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_worst_cost(const double value) + { + _current_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_average_cost(const double value) + { + _current_average_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_standard_deviation(const double value) + { + _current_standard_deviation.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::best_solution_trial(const Solution& sol) + { + _best_solution_trial.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::best_cost_trial(const double value) + { + _best_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::worst_cost_trial(const double value) + { + _worst_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::iteration_best_found_in_trial(const unsigned int value) + { + _iteration_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found_in_trial(const unsigned int value) + { + _evaluations_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found(const unsigned int value) + { + _evaluations_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _global_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _global_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::global_worst_cost(const double value) + { + _global_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::display_state(const int value) + { + _display_state.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::crossover_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_crossover_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::diverge_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_diverge_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::user_op_probability(const int index, const float *new_probability) + { + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.set_contents_state_variable(aux,(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::migration_rate(const unsigned int rate) + { + _sc.set_contents_state_variable("_migration_rate",(char *)&rate,1,sizeof(int)); + } + + void Solver::migration_size(const unsigned int size) + { + _sc.set_contents_state_variable("_migration_size",(char *)&size,1,sizeof(int)); + } + + void Solver::migration_selection_1(const unsigned int selection_1) + { + _sc.set_contents_state_variable("_migration_selection_1",(char *)&selection_1,1,sizeof(int)); + } + + void Solver::migration_selection_2(const unsigned int selection_2) + { + _sc.set_contents_state_variable("_migration_selection_2",(char *)&selection_2,1,sizeof(int)); + } + + void Solver::migration_selection_conf_1(const unsigned int selection_conf_1) + { + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,1,sizeof(int)); + } + + void Solver::migration_selection_conf_2(const unsigned int selection_conf_2) + { + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,1,sizeof(int)); + } + + void Solver::select_parents(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_parents",(char *)&selection,1,sizeof(int)); + } + + void Solver::select_offsprings(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_offsprings",(char *)&selection,1,sizeof(int)); + } + + void Solver::parameter_select_new_pop(const float value) + { + _sc.set_contents_state_variable("_parameter_select_new_pop",(char *)&value,1,sizeof(float)); + } + + Statistics& Solver::statistics() + { + return _stat; + } + + UserStatistics& Solver::userstatistics() + { + return _userstat; + } + + Population& Solver::population() + { + return current_population; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool worseG=false; + bool betterT=false; + bool worseT=false; + + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost > global_worst_cost()); + betterT = (best_cost < best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost > worst_cost_trial()); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost < global_worst_cost()); + betterT = (best_cost > best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost < worst_cost_trial()); + break; + } + + if (betterT) + { + best_solution_trial(best_sol); + best_cost_trial(best_cost); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_in_trial(current_iteration()); + evaluations_best_found_in_trial(current_evaluations()); + if (betterG) + { + global_best_solution(best_sol); + global_best_cost(best_cost); + time_best_found(time_spent_in_trial); + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + evaluations_best_found(current_evaluations()); + } + } + + if (worseT) + { + worst_cost_trial(worst_cost); + if (worseG) + global_worst_cost(worst_cost); + } + } + + StateCenter *Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::RefreshCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().selectors().size();i++) + params.pool().selector(i).RefreshState(_sc); + params.RefreshState(_sc); + } + + void Solver::UpdateFromState() + { + best_solution=current_best_solution(); + best_cost=current_best_cost(); + worst_cost=current_worst_cost(); + average_cost=current_average_cost(); + standard_deviation=current_standard_deviation(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().selectors().size();i++) + params.pool().selector(i).UpdateFromState(_sc); + params.UpdateFromState(_sc); + } + + void Solver::show_state() const + { + cout << endl << " Current State ---------------------------------------------" << endl; +/* cout << endl << "Selection parents -> " << select_parents(); + cout << endl << "Parameter of selection: " << parameter_select_parents(); + cout << endl << "Selection offsprings -> " << select_offprings(); + cout << endl << "Parameter of selection: " << parameter_select_offsprings() << endl; + cout << endl << "Crossover_probability: " << crossover_probability(); + cout << endl << "Mutation_probability: " << mutation_probability(); + cout << endl << "User_Operator_probability: " << user_op_probability(0); + cout << endl << "Migration_rate: " << migration_rate(); + cout << endl << "Migration_size: " << migration_size(); + cout << endl << "Migration_selection_1: " << migration_selection_1(); + cout << endl << "Migration_selection_conf_1: " << migration_selection_conf_1(); + cout << endl << "Migration_selection_2: " << migration_selection_2(); + cout << endl << "Migration_selection_conf_2: " << migration_selection_conf_2() << endl; +*/ cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current evaluations: " << current_evaluations(); + cout << endl << "Current best cost: " << current_best_cost(); + cout << endl << "Current worst cost: " << current_worst_cost(); + cout << endl << "Current Average cost: " << current_average_cost(); + cout << endl << "Current Standard Deviation: " << current_standard_deviation(); + cout << endl << endl << "Trial: "; + cout << endl << "Best cost trial: " << best_cost_trial(); + cout << endl << "Worst cost trial: " << worst_cost_trial(); + cout << endl << "Iteration best found in trial: " << iteration_best_found_in_trial(); + cout << endl << "Time best found trial: " << time_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << endl << "Global: "; + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Global worst cost: " << global_worst_cost(); + cout << endl << "Trial best found: " << trial_best_found(); + cout << endl << "Iteration best found: " << iteration_best_found(); + cout << endl << "Time best found: " << time_best_found(); +// cout << endl << endl << "Best Solution: " << endl << global_best_solution(); + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + } + +// Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Seq::StartUp(const Population& pop) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + time_best_found_trial(0.0); + + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + UpdateFromCfgState(); + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + if( (current_iteration() % params.refresh_global_state()) == 0) + UpdateFromCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs() ) + run(params.nb_evolution_steps()); + } + + void Solver_Seq::run (const unsigned long int nb_generations) + { + StartUp(); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + void Solver_Seq::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + // Solver LAN ------------------------------------------------------------ + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Lan::StartUp(const Population& pop) + { + _netstream << barrier; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Lan::send_local_state_to(int _mypid) { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_solution_trial() + << current_best_solution() + << best_cost_trial() + << worst_cost_trial() + << time_best_found_trial() + << current_best_cost() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << pack_end; + } + + int Solver_Lan::receive_local_state() { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_solution_trial + >> best_solution + >> _best_cost_trial + >> _worst_cost_trial + >> _time_best_found_in_trial + >> best_cost + >> worst_cost + >> average_cost + >> standard_deviation + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + << pack_end; + return r_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualizaci�n de las estad�sticas // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Lan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Wan::StartUp(const Population& pop) + { + _netstream << barrier; + + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_cost_trial() + << best_solution_trial() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << time_best_found_trial() + << worst_cost_trial() + << current_best_cost() + << current_best_solution() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << pack_end; + } + + int Solver_Wan::receive_local_state() + { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_cost_trial + >> _best_solution_trial + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + >> _time_best_found_in_trial + >> _worst_cost_trial + >> best_cost + >> best_solution + >> worst_cost + >> average_cost + >> standard_deviation + << pack_end; + return r_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Update Stats // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Wan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + + } + _netstream << barrier; + } + +} + + diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.o b/ProyectoFinal/CHC/malva/rep/CHC/CHC.pro.o new file mode 100644 index 0000000000000000000000000000000000000000..41f66470a6785a1cd1b0639260dbc9f227f6ad39 GIT binary patch literal 191488 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.req.cc b/ProyectoFinal/CHC/malva/rep/CHC/CHC.req.cc new file mode 100644 index 0000000..df05c01 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/CHC.req.cc @@ -0,0 +1,332 @@ +#ifndef INC_REQ_CHC +#define INC_REQ_CHC +#include "CHC.hh" +#include <math.h> + +skeleton CHC +{ + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + Problem::~Problem() + {} + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + + double Solution::fitness () const + { + double fitness = 0.0; + + if(_var[0] == 2) return 0.0; + + for (int i=0;i<_var.size();i++) + fitness += _var[i]; + + return fitness; + } + + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + int Solution::lengthInBits() const + { + return _pbm.dimension(); + } + + void Solution::flip(const int index) + { + _var[index] = 1 - _var[index]; + } + + bool Solution::equalb(const int index,Solution &s) + { + return _var[index] == s._var[index]; + } + + void Solution::swap(const int index, Solution &s) + { + int aux = s._var[index]; + s._var[index] = _var[index]; + _var[index] = aux; + } + + void Solution::invalid() + { + _var[0] = 2; + } + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].worst_cost_trial + << "\t\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t\t" << userstat.result_trials[i].nb_iteration_best_found_trial + << "\t\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + void UserStatistics::update(const Solver& solver) + { + if( (solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().nb_evolution_steps()) + && !terminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial = solver.evaluations_best_found_in_trial(); + new_stat->nb_iteration_best_found_trial = solver.iteration_best_found_in_trial(); + new_stat->worst_cost_trial = solver.worst_cost_trial(); + new_stat->best_cost_trial = solver.best_cost_trial(); + new_stat->time_best_found_trial = solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + + // User_Operator:Intra_operator --------------------------------------------------------- + + User_Operator::User_Operator(const unsigned int _number_op):Intra_Operator(_number_op) + {} + + void User_Operator::execute(Rarray<Solution*>& sols) const + {} + + void User_Operator::setup(char line[MAX_BUFFER]) + {} + + Intra_Operator *User_Operator::create(const unsigned int _number_op) + { + return new User_Operator(_number_op); + } + + ostream& operator<< (ostream& os, const User_Operator& u_op) + { + os << "User Operator."; + return os; + } + + void User_Operator::RefreshState(const StateCenter& _sc) const + {} + + void User_Operator::UpdateFromState(const StateCenter& _sc) + {} + + User_Operator::~User_Operator() + {} + + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.best_cost_trial() == pbm.dimension()); + } + + StopCondition_1::~StopCondition_1() + {} + + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool terminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} +#endif + diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHC.req.o b/ProyectoFinal/CHC/malva/rep/CHC/CHC.req.o new file mode 100644 index 0000000000000000000000000000000000000000..5120ba4992fe5f72ea6118d14c689c490b673b40 GIT binary patch literal 25240 zcmcIs4SZD9m4C@Z7(g?FjhGgdfsQs%NHY*1qqUvM7jGnBWD=zEF-#^CGMZ%K%mhLK zr8~j;e8k39Emhl6>#DnJw{*4pv(#b`5NvD9Qn%$-x0Tut`S63HmR51I=iGPhn=>!- z0DtY?A8+ox|9kE^=bn4+*LyeI-q6%oTvVjUP^5fD$>k)fD9dilr2`@vP-ZDJ1g#75 zSm#oT%PIaC#gi$%oZ>4e_E0>HVlTvR?{Q5DC>@oqDFcvG6ji@KMA>1ts*OE{>7kCH zTzOd4-ajfRv{!ba;N=F5tiOLO7Vhbg`Cx0Xr8TT(Uw5kd*m}KE)dNRW{fV(BflA%- zhHKy^XvyYHH45-`4eSEcwX3gA)m|YX`$Zhm_NqGQ7C0KxpC~cwUO{zT1K+2LP1<XD z71hDHPy)>N?JN_q!B5rRs@L8;8|ytljcU0D?t&ERG>Ub0uT#|yFJBp45nKsYB>QP^ z84BnP%C7M!QV&$A*9fD!2D~F9BOrU^pljF3W0yi^2y$nkpT+4t=cZrA=@&vq@aFvo zy%Eyh3I709+j#)>)81FV@cKcK`jerGVY4RfRaJY<H*8>E*lUo8_U_5~gR1>?59j|h zIwmXE$L`7ZAAO3dofbU(dtCPpFSq(1c#0tr%$q$~v}Y*aKf(WgrD|`3L%9ty?Uhrm ziS=Hi(kYi4lBZlV5Bi@2=4y7YdwITmtG@@A3J+Da4}kM&Fpc24WmwzOU#-U8SD*f0 zup)#hs(-)hi}$0McE46Eh_sc^{|!o$7Izy?5L~rqs7V(N7t+U|w=UM7s6uaDwB?OV zTM+#zQyDaz$*_T{kwY3b-#J6{gMl5}2y&aqKSBlkDf0s;6~1)hyFw%JlW#9oU*HA{ znBzOx64K7Js@l6@-^(W^bquM%7d%@Xtlp+(_Y?^ZrcaV`{=>H)ZqklmBln=ang(Zq znhLUd2UvZ8tU$nK1Veg>cPIKlllCT#GCiMfz4jL&!aA5h#J=UKc2o=|uw&l*5z;;| zrVzc+xn=ma=^)nkhVNz9lzKxRSOHYmt1Hy(z7oMcc+Cp0bK~!!|D8?RQFDj_J@)q5 z_^H~PAxE{>V0m_a!ZTq!p)qk3>7Ui>K)=j*b<0TR0>hHAP0l<Q(l$6<U&Lw4^dfx& zc#&hvi0kg(g4I-gk)jUX;8y(y)xl<W!1a~qRsVmvzVcka`AgTpexS&XT<E$3=Sfxj zvF|VH?&HPk>0f7Gb!4XNzU+HNTGcMJerB?MYf1LKVy(AiS25-%=(jqxUgs_cWP;jz z4Zar|d@l#5AJPsr4A!1ecfVTPH0YhE7Cjf-eY7~39WJUJoVf*Pm5w@BvgE=b7`WCo zv1EKGyW8F1KfLZ}(VId4@yskW_RD&`<eqx1WN2_{k^j9-lhxRv?DNG4`cET#+c-7$ z7rpFzTG<YoE@8+kzC+N(&>wpBJzDjUntiUw|Et?iNdjR!VPEKYFs=5kSV4@%W&Z*v zDki59RjY%g3Y?9W4CwRaEB9nKIC0ij^=tC_gGN(sJcLy}0@dYc{H+|2%f;LS<KrCj zk?4Oh0<IG65#wpln;T5pbGwgEDLR-vQZ)TwP%H7O`X*!M0+&A|hE(4C2&-harZ`ih z-{{<O=r&*Wcu|MztzmVrWvE2(hujNlcDUq}YleD8^*?vYwQP6aah%nR^#`f>cn5xY z^K;&yo!BuH)XN@1owYKdGS}`8hIW?uM6Beu)8q@b-hHGvU*7F*+BJ|p#zOb2gJnC! z%J9iztvF8~Rd=a+F?vYJ4u8q_VA9T?ud(v(KNYLmN!2l5brkERx?6K<lYmO{->;yD z<CFpZ1nm{_N_H44hjo1dy8_9ULzzh`4AqIy-9lTaY}n7bKB$JzspNF~7r4>)*!*;3 zaOutfK*q#!Mod(ls+RFOY40I?8K*^K`|=QNUtV?%EExlPj19QQ_!8_7T)Wbv_ZYM+ zd>RDEDYGD}u_miY=U`QPE>_O~14FA%<XHLMFy=G4T<NgP>H+tbVb|T?0qZwuzgwi8 zS%eGd&tyL|d0{eCb)W0*gD~mfR&RER7`47bCnlQq_8)f*IH4RS09C);>3^>8jgVgE zg%SC-%YD;K-=Vi%6IXcMCtS3?ApKF0m`8u9LEcs&$lJYTC)~0>k^TUu-}r{AH+h>? z9s2&Xs$b{!9a6O>Z`Fy5g#RG@<D=<Sliq32moxf1N7Dxkdf1QL?C~9f9ZHwib7BI_ zd&s|YG<^-w197Tc5NEs<CrS-FBE2f<*MfaEf_)kky_|L!A$?#B?l8ccT?0j6;LZK$ zP**|~*REc0sMFbfa#c6B6`DE6k%Nlm8U})@?Gc?UHc=Jkd`d0|3}HgeC-PW{aCKos zs-E$dp9f9VIcUTbsJ-&G>!x~dnc;|qwc>;{MUkia_qn!qelRk!NPDN?0D2zUXLx-? zn9g=Af|YjG8qG8`(H%Ij;Y{N&`T-n$Ju(xAhk#%<`alCalTO-F1y=@F1tTzlZw9Uk z?9Pt8e`aJv`fo@ZIW`&emU&g%2+phh?btN}1Z!{fs+eD%%Lg#OA(yYg{DVe5q`iCW zhazdrccQoIz00UAkfKwITh*7q!Q~QE$~Ev5Q~}bFLwIm`3^Hg$7@_?$L;6@4q8q(# z%vGph?q-oMGY)L9w$^*A5QZTHvvUA;JN4ic0Kgbgz}Nacn5ls=ve64k0hNnf#j%Mf zRv!aO3t6hJf*4a6$-&V}d{o%`BOA<u<289DqXS@4)5&zl=#$xt?+F6qWHxMMWdDw) zZsF7m&PDwUr~dA_s0W0pUokXUCo*R{B0g+T807asMraLtC!>FHzaG;5S8h|`^tI*X zOjU0G0~@3!{TAo0D(GgTy>zZ`(oTpx99{Z;9oi4;3k>b-Ch*YxjZVx2_cw~Q&^1s3 zJ5IepEC$a)0q)F|XLAg<42QIRu7ML!q%Q)uYE`zpaND#kumFA&sfUeu@vv)P2(qyA z1jlpw58ygb;(ZohF{rvbq_slS?1b0}G3J3&b2-G|OU)jL!FK``A+4c8s2$3F23DmC zb$>u83$ai(Ge4v+b;4#=)oPu=Y@@r#zY<&&88$jyUuuLC*YYOqq<IV(3TZDLO9Lus zp<YNEbInSFdTY6b8qDKVTwDGON5&IBP<4F$0^^gmr8Hs95!gN$OG3@uQ7exOCmGzv z=g5rWXF;OT!Dj#BdHxLSVnxS(VhH+EE!dwb^(VY^>HGEa(EbuHsu$W13ppl&kPsHa zLmoRX8V4_8UxDYv^Wl#NFW7{`&K9@tMoamNB?q3$#d_Ns);=&gS#Gp(D{n3{$VeOt z_TXloTr<ydf=kYy!{!^G_ji^;yNLGia@rrBOP>PozrdSw{Ecnif47F=5DG_MI3B<} z^O~ytUI=Q^j)~VM(1h1W@@v{YBbD7-ZXQLA#t?-uy2&2m{S5Z!7<|j2ogQh1ag`Y- zw&J)Gm;N*`oH-%W5CcQvMt<erm$|ZF`EfP30RSeC<_%O};~IDj%*Lw1D-OY08y0dJ zj5jSZXRNX?>o#~~9n6@kKFrY#=3W9bGevI;j-l+Qy&!4yAe|P{TVVeTLllSR@(`>T zFj&Dsi_kkokB77p?}<PDzYMbM&y695!$Q$c?pfT|-4;)Ik{zC<(NrSZ))h~Clq=g6 zk1|dfhyTVYt!W^*zBitVW|FB&tk=>R_oNe_k7KoHDivMt>F!HsJZ*7LUoX&kGM&+k zr^+*R>Qtmwl<~9vzF=@s6wl}oZh=EzxFu8<_FUiSX;~5qHibu1dB%B=$KR&~);2V0 zNTrggt38X8p6J?WR|1UY>5g|NQ|mn)$&_bWceJZ38Jp%w3Y#U8JzxoCWTeP>d0CBe z1Drb`ec?qAf9!(k%BLy+QHW<;(5SRPEQ30DEhclvblu1gij9k$3}6-!$2?gp7cZVu zr`GxAU<XEI2R7u2N2Q29oJsc9C41Tv8PNUQ^mFs*BfhiM7$x!_3oNLsyV_H+U~%ho z&%Danl|IkxD&M>+zi*zWVoAK+qk>xseAevgC>Y<GV<`Ik5~Zl$T{QW^vCbh_nsBYS zOq3`J?)otxRwYu3IFd`Op0JNljBENbO5-;SC0Odt7T-|nge3CFAO=BvN`SZqo;wkM zFo4TqZK->(xVE%>t0P$IxuYalT9Lh=zO<_NrSYW|^`)L*X*p2TmO4Wdl$k)j7b`+& z#2+ZxS_~9-IDj%+(o%Y|C|2sJFD(ZppbE-=2k9V`7?IG)iE<%`eGtS*cNt-_{n)N5 z!Y+oi(XM9EF0^A4l}*I5`ciiYO3;SwgyY`8sB>MZr=!#zgmRQ4+6*zAB}71bY@<4d z5P>$`jrJIH)Rua-qCM_Fdt}FK1cQKypvW*t?F8ia64jN%r~<H~gasgN*a%EQHcCn3 zKoQC=BSqE_Ey)g{?0Qpn@dD8qrffy22Kr{IyO8QqKSE#R`Z1H=i=rN$u`zs@dZ_C# z)mx73v-G`VM$vfLwE77*nd#t!oNpI>zPU+w{@4dm{AB6>=vQI~1@TgNgs*@L-GRQ9 zbwCFu41Umw$Pay^i5x|24291xGkv3z%D8V}zicMF4$@Zr`=#<wg#G#i(aPBcv0=ib zFC)*F2=hVO+Sf706Ma?=0x_L}&n_aLEGLHJkOl(Enn{?bM_7O`IrfpRg|Lr88UtdT zgyDB742W$c49q72Vnc*cB<LQY%rr*#G+|<X0lW#GpAz;}9K_%YU&1kSw_`!6XRxHU zv|=lcnLEY=OKY-Y>r1y6Ij$@jUs?kgj3*dZrX#DU5AwT=2GC*hEgA<6`D4&=C3qQ5 zOD2Q52~i6YoPhn(Mf_SJZS+fSp6V?vUoIvnDDuLyjcCPcm-9OilMy|La|im|FwqHH z3!l4D_#FE0A82d@AuUXk<Fl~TvlRRnI-L3Mg*5r$cV=UrGW-|iR8W~!4)$3+l}R7K zx0$QS2R{dCAshN*)Ld{~Y2aqCR2`eraV+7u-bOt20^|Ayb0jxRD1HYrO~P`G*l*~Y zFHv2wQCnE*UL`C71qA}?U!weZq(G74P^4$(mpYV-@&U>@6g-iP4h{vs=#LH#;oXIB zF-wdpa42HcDS%7M=Zes5#YzqrwgAkyJCM^8>11#yViu5DGj@oZ2xityID`k9Su^2K zga?^<nQ#c{GM9@TikLBT0HquX-fS2h9ExW&2#7<GGemx|!<@;j_$TrK$~hDqt@!~z z+#0i1KK?1ft(L>JP*Fzrqo3$;O!4p;k(p@juVh&r;r$YzSS9>v3%*F?-J^P73E^^2 zC#xCPP~6HC2~fOJ#GpTS5Wr#rcPk$!IvzQct9aH-JFHBo#9{7uOj40>Ku;D54r3-6 zRpd};610>!%-vjmfy3N+T5)GSKsg5-1PcX+B3H9qX#$ed*m##M836oZHlNVctUP0b zziWeE0{u~l&qBg+KEohKeh1(ZGfIr#jet*8JSG&N)crQ}{{cA4mAoYX7YVPT`f@$S z{idWfg+SsY(Kiz)&j2N05ae&g%L!ji^m4CU4R|5`0ULa=4gQb~{-_PU-v)mLaMT~$ zhoRAkl=p1tF9OFXq<<OU$OqejL9Cq+&m>&#uW5->LWHj-ddP~<L3l6Wa^<+4@FBwG z47H8$9fZ#zK5qkFNY6>2m}oE2Q>4tW!9PQ|9NOYs12R?vUWk8(4c=>m-($o7Ny3jn zJ21$Z;wOZkBs?HW73DP>{-=n(3Stc6Yy`0j7@{4v6TVQC!dVFLLhWiK`jZy=n{DVf z5q$t+4C0&v@%=XRUnlzQ<REx<!SJ7ePc8Nu8Tgem-60!3KeEApXT$$J!sXN|SM)N_ z1MTCXfiC^6lJEfGb)?xMzzf+8zojFeA);>}`X0iM5Kd-Qwi14la39fshwv&gfLynq zC%l<(IpZHCd^O?n?1Sw@eKr#==ff)q-%hyLFN5r>2_Gh0t{km|A0%AvIJ*cxLbz;~ zM)*m>r%}7UVS_(OxQ7}f=jWf>;3o(V5WP4{feaVOE7UI)Hh2(lw9gUR`ie6Y@QK>c zciP}RHu%FA7S`uqNbWE>S}WP-1;RZv5sGsal>N~LFM{@?{;P>z_Ty!M7qUZ*4SksK z&BP~2`lJazNVwcF-%t2Si`*vxFC_P8fKO%nUb(M4Zo_9RI3BjkO%5yl)(dzc{-3p> zUqN^kF~D;khHnx+M7TJ=0sd1P{zq-_i(nuW(&tJW{019*jSYUM4gNzL{B;}LZR3Z2 z8+@e=-e-dkA}$wKVPWIv0UP?q0H4avYm=zXZh=ehFy2>T(aSb`O5liF$o^9RpUO@b zlD}Wzc)B!#tQ)rBvtH24RU)U)eFD#&`%H}^3!1L44K_t0>Ato|C<1TwD^u}XD`PPw za#J|dR1=9Ll8K%~MyYJ7tHK{2{>;XoIruXdf9B!OeEg}wA3y&13~E8{n+@C+FAQhq z#xm=B<DpnXO?xu3F3}$EX+S}Rz9#tQw)VD1Gx5e$vOAoCM8lGWKA%X{#d|XGlweul zGsOIOe>~QQ^z)X8Pe`HW#o<UzIN8-FzB)A62%MXaXZm^@nuS6O3o!Q0UJ~y}#nYX( z>J+F{Kf7VAB8_}~V`I3XCDIbCZEA>s8ZAo;wLGU_b*Lwkikcr-3|<ATRqsPFg^Q|0 zQF~YO+HOfQzd4nJZ%f^ELOY|Hi7{4P>4qiY<dTJ8Kv^ub3n%CF_GOH|3n%AxboHe> zg_Ll{H!l)NrZcH{v^$dMf$u|^Pz+FCtTUR5Kx-12H1t2P&G_cDMbn9xqz-{$sv-^H zd6DLY;W?2m)D=1{-H^Z(cOKuI$RfjgKtdwJ1ZO%^$#s#oXnQ0UO=nDtq_7!@C8JuA zn7<~T=}Pp(q1U@&N;(~j_H<Zn6b*ytg{!c?77MqKmhiVHQt_DZDIv*P*d6al<7ckX zh4EW$Sb`>|Ea6PnFJQj;4e(vC4~9eTGg^N4h}=9d+}d~wm_eIi)WkEbz0J{7v^y=j zPiRUszPWAjbS4smK7;N_M7s=qQMzm>_d63~USf_daHo7_z-B#B^ty1SI+pCqD3M64 zKN`t(lNg|pp7^>*SG;FUrc)X}$I>^NrO^#0$(-J{?wr!OzBUOAmrY=a@Fi>;^Xz;& zS?FIJ&xC~=izek0<qD;LVl@<yD?xX&tCgpUNyI#@J=$z~uURh4i=J42BTUjAm66Dr z{{9Gj3Qi|`;A3%SePnHw5^3#Om*{DaEQzQ4y5oiI$-UX+KFTT0602951->dAf8aCl z#U6Sf742z9fx^8^qWK+(Oiw(WX5+vt^JkI~Fmj@2O|ApYLZ1&y<+RP_Ws{;BuL>06 z>zi%3Q>dpF=9>b%t2??9y~fOfJ!f*97r(VH+SS&OSVA_+E3Hnii$bk}W%Cm~_{F}x zfUr4hqp1S2{D$*m;po2RW6snrZ<epdkMFn?CDNHhEDg?Ka`9Qq*kEOjZzZFt-4C-X z&D`BMQ72o(+!s!=f_7GbCbF_JUD>#?0AA6vj^=@QPkYygUJ|4qTjk7+b;Y^;tmWK{ zqso|7ELR!8m^bG{=C8teW%)NC>U^wPe$l)btcb8FG1>Bd$R`!uAdG6A{qy>GPTu7R zDv~=2Yt6Ip<W{g&%QIiTz`UYS^*GZi*sOIYdZ6_;SmyHcS*r?p*StQlH8i-%wa%P* z2=IfW@f9s^(VHLZOQm2N8A*V0Fog1!X<|Sd!rbzmw~+d3dfFoKwKP3N(wTTKpW=u| zZf(jFKSzpZD=sIP<BJ>1JSdiqhy}VM*$3@O^w>3Nw%=^Z`Bm`ETbE1~SoyggvwfLF zcbxOHQP?+65T<+4ri><>sYxWE1<`aIHnWKgj1XZ@D{jnek@j>l(g~|b7c5+2rvOgV z4~GxfDu?a1$}J(=lBJ7%Rmi75+Ll=Bn+@r7A`<J0rqdBThk!LZk~lIX3(J066iK;x zqm5U}9~Pn{U#@RH=uki?akh>f&U<tjodf0jg&B~a2M^rS7GW-x<9n?dhCje?{3a&p zA7=Px8U71~bNZJV&gowz9FNp^wv_x&G5P?*KVUe%yOH#j^qwE}=W^#UoXc%tcrD}8 zNjTaEza>ik@;e9e=k)Skkd^)^8~z7u_#a{P`0iE8b)jJ(pj>>%D)C8#V}$R*B>r(m z-^lQF3=c8<K89b%@Mjplh~YnGIOlUQy|+g_IX<7^H!wb7!qIL^7`}ng^M1@SocH5h zgri#c&Q99ltBgLt@JAS4%kZZOxAx-;j6Tfhf5z}ShP%-K5HP}Txl$i_e+O}V2P$z7 zqtCM&;n*&GizDgfy&WtLFg(rp1R1`8;aqN(;au(^hTp{aOoQ(U7_fK+JW`*V7`}?( z_?-j;((`_o@2?T(_S^;U^)VpM^?Z@xE1^uvJ<f10_Y}jUjD8%vN5^30U&io-P%imj z$?$fDuVnZdhOcEfw`Uo=&&GgqIqtW?SB(?o3idnR4Uqc82uD5vhJTsie7rosa6VqX z#rWgfKFR;z89nF!8-{cKe`Gl4|2pG;1>^rWM$h@r7!O1cuw9)0Y=(3Ge}ebE7_9Vf zGMv-@mErwRPquf2aJ2IjhP&YXD+a5bFK76AD3^S^gd-mh!>bv6fZ??a=X^qp&s0YL zIY!U<bTFK^tJ{XpCPvTs+{JLt=N=nA-(vKf&yx)2?b^xsc$A#oe$41OpZ{Sv=W_+T zhsI#-_p2Dr`+XMS*e~1<uVwTBD3kqo3&Xh|rWwxpkE1JFs8229GnH`bI`WnceKCEH zv(jHqxRrmE4gEqJ`c*dc>uu<_+R#5{L;ph?`d=`5zCK<=A0n__S2Md^ZiBC4_y$J* z62mt#d<A`HM0@gmMLXdrcN3$(g>dwfX$;@M=mQMTGMw|#ZSXHM{(K#On9+0o|H^RA z|0#yw#`O6O!?``*u)(jT@0eEmFS5bo49_yTU4)~Z`8nclM$h}@L52@7KHq0J*Z)Th z=j-@OgkyhwobmY`qYp6rU54Mu@H2#?{u;wSLI)%(ejVXxx4Rhqa)viCJkIbzhHtXL zw=kTy_bG-CF+Rf#zlY&JVfdFB{tJeGh2cjS&goAu{9Z=?H-_KM@Ue6e1MS1d>12lA z$LOzO`27s8X82bbUd!-p48NY?ix|Fw;a_8Tg5eJ^yr1FRZ+8=p{;-76zrg7EI6X+X zbv`-5=mU(;QHFCqCvEW4j6a`G#$EzUA)x&O@W^$|#c<C5Qik*S1ouK1kk5R0Bp;l^ zF(A&zX{*gX*1`6BtDuhLGllujR)#wujREb3G9*212L$#Y!-)<24{eI_5W_zPX$;8c z>+ncExTnHk<&X6-pv-T;Bk2*tPy`P(MdalV;@^UYmLY}AAn3m-iC8((Kg@8MMEsxO zDa7a7l8D7;llv&6ll+kW5r%U;w=<m6*D$=C(#Xfpa1X<M46k7LY=&1cd=A5<EaWd~ zu$b%l7^CNU;(Tij$fu2g9!g`s(~(pl)eOfn8B|IjhL4oD!h%a(`z?4g<<Yk>NIt7Y zPEig}EOB{1^{*B@fCLaO#0Ei-^v#5OEcj}|t1Wmh;msC&h;aG73$ys_ApA}X{Yk<f zvf%RmsJu@m`N;d7uUqKl{Z70`j6u@Ndz>v6d^-+I2wN?<ysx>}g3EiE6KF!g;?>B2 zf`{Q)ChuiVXSnn|tkTSIA&SoVT^3y4ryQ{0@;>Db3oh?X?zQ0Z-sE8mF7Hj2kUdZr zeB`~!%PhFOH!1BZ=~q+Z>Mit}314Qxw-erF!G{UoY{BKd$$KsM5u$(Gg3Ei8&scDI zKk}djm-iq&G?-<(<h{mT3oh>+K4if?7h~_j->O=0dB5<81(){)k1-sZB-bZ5y?2uO z$a{n{Ex5c#s9JD&|8Io_m-qSN3`e<_q4E$OVmQi{_xuhsJa7G~Ot0_GMB9`~xN2j> zoide*cSS4Vy9wOcf(ukprLrxZRs>LKxk$rrVO6G*NR9k_m2hi|XW>@Ynpi9n?~lcM z;qwmuEk6)QF;FF%f~!*m;gx`h__S>@vHyHya1nxm9|#2%<<}VNS5c`F<7W9Nb5?Gn zXpQ#fxQ+hUayEYFNo{k(s~~5hJuBz4UHzzxCA;C$5%hacG83<aKUSXwT@$;7Iwsy3 z>3}Oh&~<B4N$9SBM7S25m5!)+>;jad=|cG=<Ua)uO#^0ZS6?kqANOPDTVJl<T>kbC zQGZzh`QQE!^;Z|D|Hy}^-&vskqaUKa>|Ne|+<%>~{p5a#*T?q*=Uaa>&|={A@qB*1 z_3sq5^XsoJP~QU>ZcS*Kgp?76D4tB`BZ<3ZLY6~}It3^%BlopNY8zER|HW6$vOVQQ zcooDbpO$$-73JS7a%BN+qhwb6KMTmyuD+Gtn#VmmVq<X8U||QzxAL{NAJ4*ApYQRJ z&68B$ic9%2j@r~eO7-PF7I|Wj_LKE{0mHOKedRLxgNm70i3M3tLSKXgV%Gj|ruvnV zkYa25{|WFy{r@<=gn%$)L}LEJv#Qiz_CLORz*oXnJ8vfWlAhR@^=1A(NEDJ^v)G`J za?t<Kq>`V+aZV8SvlwuQ<WDl#n7`Kczex2RmimuVeJMvWkn&~z03-_O-%R?eM2Pw$ zFIivmeFv~Y`VXI{{*$3H*0<_^nCe^GE9FBK5hg+9Li%qb{i}!$^~d)#vcA;6mgE;( z?03?}epY>MvC-d20;C*L!;~-c_;;v<^gmF*{#O*x|7$k#JtR0F1yL;9FX4M_<h!po zC>|$5w4VnaSzoqmpN;(0=h^;Y8~IO@eBOW43dn!kMt(oZm-<3g5v=()ZR8&%`LdnZ zelI+-zQiv9zX29`?@Un8W+Iq{85WQhgN(1B`UaZ&{f-ongG5T!lkgm>4^dv&LG|(P z^mvf^ORN$q7V<y&2ghzYXJPv*;F0yEdboGA&Yj5H-HN~Pe_&V?v+9p|3yG+=jb4Bb fyF^y3v!8;bRX(1n3dvuF#1OuBkrB&ZtNi~1Wu5K< literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/CHCstructures.hh b/ProyectoFinal/CHC/malva/rep/CHC/CHCstructures.hh new file mode 100644 index 0000000..70aba85 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/CHCstructures.hh @@ -0,0 +1,29 @@ +#ifndef INC_CHC_mallba_hh +#define INC_CHC_mallba_hh + +#include <iostream> +#include <fstream> +#include <math.h> +#include <limits.h> +#include <float.h> +#include <Rlist.h> +#include <Rarray.h> +#include <Messages.h> +#include <mallba.hh> +#include <States.hh> +#include <random.hh> +#include <time.hh> +#include <netstream.hh> +#include <assert.h> + +using namespace std; + +struct individual // index of a individual in the population and its fitness +{ + int index; + double fitness; + double sel_parameter; + bool change; +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/CHC/Config.cfg b/ProyectoFinal/CHC/malva/rep/CHC/Config.cfg new file mode 100644 index 0000000..b34042e --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/Config.cfg @@ -0,0 +1,3 @@ +CHC.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.chc.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainLan b/ProyectoFinal/CHC/malva/rep/CHC/MainLan new file mode 100644 index 0000000000000000000000000000000000000000..f71c6e405ea5e9ef5a0fe9ad9c3c33807afa6d2a GIT binary patch literal 150656 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%0A{#|8_WyPi?W%6s~sep*?E<?DL`<;BiC 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%0DU33JGmU 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainLan.cc b/ProyectoFinal/CHC/malva/rep/CHC/MainLan.cc new file mode 100644 index 0000000..279b550 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/MainLan.cc @@ -0,0 +1,49 @@ +#include <iostream> +#include <fstream> +#include "CHC.hh" + +using namespace std; + +int main (int argc, char** argv) +{ + using skeleton CHC; + char path[MAX_BUFFER] = ""; + + system("clear"); + + strcat(path,argv[1]); + ifstream f(path); + if(!f) show_message(10); + + f.getline(path,MAX_BUFFER,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(path,MAX_BUFFER,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(path,MAX_BUFFER,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainLan.o b/ProyectoFinal/CHC/malva/rep/CHC/MainLan.o new file mode 100644 index 0000000000000000000000000000000000000000..719588ecb004d2c7131a859e6905d3a50cbaa302 GIT binary patch literal 8992 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 X!Oz(~-d=9)%Xm|PyoQ}4;%xuFo}{|k literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainSeq b/ProyectoFinal/CHC/malva/rep/CHC/MainSeq new file mode 100644 index 0000000000000000000000000000000000000000..eb6ade233d92ae2f16601f662f46bad816b80747 GIT binary patch literal 150704 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 Qp3#=xO1~%KUVi)k4_$gbC;$Ke literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/CHC/MainSeq.cc new file mode 100644 index 0000000..4c291f8 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/MainSeq.cc @@ -0,0 +1,43 @@ +#include <iostream> +#include <fstream> +#include "CHC.hh" + +int main (int argc, char** argv) +{ + using skeleton CHC; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution" << solver.global_best_solution() << endl + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainSeq.o b/ProyectoFinal/CHC/malva/rep/CHC/MainSeq.o new file mode 100644 index 0000000000000000000000000000000000000000..2f4acd33d6c1a0632a10acbd32adcc384510244b GIT binary patch literal 8624 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 O6(AqTdFYmw=lcKrSUQ9N literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/CHC/MainWan.cc b/ProyectoFinal/CHC/malva/rep/CHC/MainWan.cc new file mode 100644 index 0000000..4ee19e5 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/MainWan.cc @@ -0,0 +1,52 @@ +#include "CHC.hh" + +int main (int argc, char** argv) +{ + using skeleton CHC; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/CHC/Makefile b/ProyectoFinal/CHC/malva/rep/CHC/Makefile new file mode 100644 index 0000000..3225d38 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/CHC/Makefile @@ -0,0 +1,24 @@ +include ../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq *.o *% *~ + +MainSeq: CHC.req.o CHC.pro.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainLan: CHC.req.o CHC.pro.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: CHC.req.o CHC.pro.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -np 10 ./MainLan Config.cfg + +WAN: + $(RUN) -v -p4pg pgfileWan MainWan + +SEQ: + ./MainSeq CHC.cfg ../../ProblemInstances/ONEMAX-instances/onemax10.txt res/sol.txt diff --git a/ProyectoFinal/CHC/malva/rep/CHC/res/empty.txt b/ProyectoFinal/CHC/malva/rep/CHC/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/CHC/malva/rep/GA/Config.cfg b/ProyectoFinal/CHC/malva/rep/GA/Config.cfg new file mode 100644 index 0000000..ad19d32 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/Config.cfg @@ -0,0 +1,3 @@ +newGA.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.newga.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainLan b/ProyectoFinal/CHC/malva/rep/GA/MainLan new file mode 100644 index 0000000000000000000000000000000000000000..4412f1cad77b8b6332c1c698973a12e75d51ddba GIT binary patch literal 172968 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 DN9l&6 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainLan.cc b/ProyectoFinal/CHC/malva/rep/GA/MainLan.cc new file mode 100644 index 0000000..494e82e --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/MainLan.cc @@ -0,0 +1,53 @@ +#include "newGA.hh" + +int main (int argc, char** argv) +{ + using skeleton newGA; + + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainLan.o b/ProyectoFinal/CHC/malva/rep/GA/MainLan.o new file mode 100644 index 0000000000000000000000000000000000000000..9385dd20caa64bf3c0a87783a4225bf3b2e79568 GIT binary patch literal 9192 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 H-Tr?8LeLyW literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainSeq b/ProyectoFinal/CHC/malva/rep/GA/MainSeq new file mode 100644 index 0000000000000000000000000000000000000000..da4383cc2eb7ad38bb626ee134b3475b21c1aae0 GIT binary patch literal 172968 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 U`w*4CS7q{F*kaPle>eaC2j;41P5=M^ literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/GA/MainSeq.cc new file mode 100644 index 0000000..d4a7c14 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/MainSeq.cc @@ -0,0 +1,41 @@ +#include "newGA.hh" + +int main (int argc, char** argv) +{ + using skeleton newGA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + Operator_Pool pool(pbm); + SetUpParams cfg(pool); + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solution: " << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/GA/MainSeq.o b/ProyectoFinal/CHC/malva/rep/GA/MainSeq.o new file mode 100644 index 0000000000000000000000000000000000000000..155133b817cf52480267b552dd709539a640c87c GIT binary patch literal 8632 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 Ih`8JTFU1~44gdfE literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/Makefile b/ProyectoFinal/CHC/malva/rep/GA/Makefile new file mode 100644 index 0000000..71b1892 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/Makefile @@ -0,0 +1,24 @@ +include ../../environment + +all: MainLan MainSeq + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: newGA.req.o newGA.pro.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: newGA.req.o newGA.pro.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: newGA.req.o newGA.pro.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -np 10 ./MainLan Config.cfg + +WAN: + $(RUN) -v -p4pg pgfileWan MainWan + +SEQ: + ./MainSeq newGA.cfg ../../ProblemInstances/ONEMAX-instances/onemax10.txt res/sol.txt \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/GA/asignacion_colores.csv b/ProyectoFinal/CHC/malva/rep/GA/asignacion_colores.csv new file mode 100644 index 0000000..8384036 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/asignacion_colores.csv @@ -0,0 +1,10 @@ +1,5 +2,5 +3,5 +4,5 +5,5 +6,5 +7,5 +8,0 +9,4 +10,4 diff --git a/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_empleados b/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_empleados new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_empleados @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_tareas b/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_tareas new file mode 100644 index 0000000..301160a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/datos_cantidad_tareas @@ -0,0 +1 @@ +8 \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/GA/datos_empleados b/ProyectoFinal/CHC/malva/rep/GA/datos_empleados new file mode 100644 index 0000000..f7cc5e5 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/datos_empleados @@ -0,0 +1,4 @@ +e1 e2 e3 e4 e5 +4 5 5 3 3 +0.05 0.20 0.30 0.95 0.50 +120 200 210 230 180 diff --git a/ProyectoFinal/CHC/malva/rep/GA/datos_tareas b/ProyectoFinal/CHC/malva/rep/GA/datos_tareas new file mode 100644 index 0000000..589272f --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/datos_tareas @@ -0,0 +1,3 @@ +20 +t1 t2 t3 t4 t5 t6 t7 t8 +16 28 11 51 2 23 43 15 diff --git a/ProyectoFinal/CHC/malva/rep/GA/ejercicio2.py b/ProyectoFinal/CHC/malva/rep/GA/ejercicio2.py new file mode 100644 index 0000000..6705a02 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/ejercicio2.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import random +import math +import os + +try: + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./ejercicio2 <ruta_tareas> <ruta_empleados> <ruta_solucion>" + sys.exit(1) + + ruta_tareas=sys.argv[1] + ruta_empleados=sys.argv[2] + ruta_solucion=sys.argv[3] + + os.system("make clean") + os.system("make all") + os.system("make SEQ") + + #os.system("python verificador.py " + ruta_tareas + " " + ruta_empleados + " " + ruta_solucion) + + """ + habilidad_empleados=[] + sueldo_diario_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + nombres_tareas=[] + nombre_empleados=[] + costo_proyecto=0 + tiempo_solucion_proyecto=0 + + # se sabe que son 3 lineas + archivo_tareas=open(ruta_tareas) + lineasTareas=archivo_tareas.readlines() + deadLine=lineasTareas[0] + nombres_tareas=lineasTareas[1].strip().split(" ") + esfuerzo_requerido_tarea=lineasTareas[2].strip().split(" ") + + # se sabe que son 4 lineas + archivo_empleados=open(ruta_empleados) + lineasEmpleados=archivo_empleados.readlines() + nombre_empleados=lineasEmpleados[0].strip().split(" ") + dedicacion_diaria_diponible_empleado=lineasEmpleados[1].strip().split(" ") + habilidad_empleados=lineasEmpleados[2].strip().split(" ") + sueldo_diario_empleado=lineasEmpleados[3].strip().split(" ") + + # se convierten a entero + dedicacion_diaria_diponible_empleado = map(int, dedicacion_diaria_diponible_empleado) + sueldo_diario_empleado = map(int, sueldo_diario_empleado) + deadLine=int(deadLine) + esfuerzo_requerido_tarea = map(int, esfuerzo_requerido_tarea) + + # se convierte a float + habilidad_empleados = map(float, habilidad_empleados) + + # se levanta la solucion del archivo + matriz_solucion=[] + + archivo_solucion=open(ruta_solucion) + + solucion_empleados_tareas=[] + solucion_empleados=[] + solucion_tareas=[] + + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + if( not (empleados_tareas[0] in nombre_empleados)): + print "No existe en la instancia el empleado: " + empleados_tareas[0] + sys.exit(1) + solucion_empleados.append(empleados_tareas[0]) + for i in range(1,len(empleados_tareas)): + if( not (empleados_tareas[i] in nombres_tareas)): + print "No existe en la instancia la terea: " + empleados_tareas[i] + sys.exit(1) + solucion_tareas.append(empleados_tareas[i]) + + + for i in range(0,len(solucion_empleados)): + for j in range(i+1,len(solucion_empleados)): + if(solucion_empleados[i]==solucion_empleados[j]): + print "Empleado repetido: " + solucion_empleados[i] + sys.exit(1) + + for i in range(0,len(solucion_tareas)): + for j in range(i+1,len(solucion_tareas)): + if(solucion_tareas[i]==solucion_tareas[j]): + print "Tarea asignada más de una vez: " + solucion_tareas[i] + sys.exit(1) + + + # todas las tareas asignadas + if(len(solucion_tareas)!=len(nombres_tareas)): + print "La cantidad de tareas asignadas es distinta a la cantidad de tareas de la instancia." + sys.exit(1) + + for i in range(0,len(nombres_tareas)): + if( not (nombres_tareas[i] in solucion_tareas)): + print "Tarea no asignada " + nombres_tareas[i] + sys.exit(1) + + costo_total=0 + archivo_solucion=open(ruta_solucion) + maximo_tiempo=0 + tiempo_en_dias=0 + # se hacen los calculos con la informacion en los archivos + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + indice_empleado = nombre_empleados.index(empleados_tareas[0]) + tiempo_en_horas=0 + for i in range(1,len(empleados_tareas)): + indice_tarea = nombres_tareas.index(empleados_tareas[i]) + tiempo_en_horas=tiempo_en_horas+(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias= int(math.ceil(tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado])) + costo_total=costo_total+sueldo_diario_empleado[indice_empleado]*tiempo_en_dias + if(tiempo_en_dias>maximo_tiempo): + maximo_tiempo=tiempo_en_dias + + if(maximo_tiempo<=deadLine): + # todo OK! + print costo_total,maximo_tiempo + else: + print "No cumple con el tiempo máximo de finalización ({0} > {1}).".format(maximo_tiempo, deadLine) + sys.exit(1) + + """ + +except IOError as error: + print error diff --git a/ProyectoFinal/CHC/malva/rep/GA/generador.py b/ProyectoFinal/CHC/malva/rep/GA/generador.py new file mode 100644 index 0000000..c699bd6 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/generador.py @@ -0,0 +1,143 @@ +import sys +import random +import math +from collections import defaultdict + +try: + #Constantes + mayor_duracion_horas_tarea=200 + menor_duracion_horas_tarea=12 + mayor_disponibilidad_diaria_horas_empleado=10 + menor_disponibilidad_diaria_horas_empleado=1 + sueldo_hora_base_empleado_sin_experiencia=110 + sueldo_valor_maximo_bono_por_buen_empleado_hora=23 + deadline_dias=0 + + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./generador <cant_tereas> <cant_empleados> <archivo_salida>" + sys.exit(1) + + cantidad_tareas=int(sys.argv[1]) + cantidad_empleados=int(sys.argv[2]) + archivo_salida=sys.argv[3] + + if (cantidad_tareas<1): + print "La cantidad de tareas debe ser mayor o igual a 1." + sys.exit(1) + + + if (cantidad_empleados<1): + print "La cantidad de empleados debe ser mayor o igual a 1." + sys.exit(1) + + if (cantidad_empleados>cantidad_tareas): + print "La cantidad de empleados debe ser menor a la cantidad de tareas." + sys.exit(1) + + + #VARIABLES: + + #habilidades de los empleados valor entre 0 y 1 + habilidad_empleados=[] + sueldo_semanal_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + + for i in range(0,cantidad_empleados): + dedicacion_diaria_diponible_empleado.append(random.randint(menor_disponibilidad_diaria_horas_empleado,mayor_disponibilidad_diaria_horas_empleado)) + + for i in range(0,cantidad_empleados): + habilidad_empleados.append(round(random.uniform(0, 1),2)) + + #los empleados cobran un bono (random) de rendimiento + #empleados con habilidad 0 cobran el sueldo de horas base por la cantidad de horas semanales + #empleados con habilidad mayor a 0 cobran un plus por habilidad proporcional a su habilidad + #empleado con habilidad 1 cobra aproximadamente el doble que el de experiencia 0 + for i in range(0,cantidad_empleados): + bono_por_buen_empleado=random.randint(0,sueldo_valor_maximo_bono_por_buen_empleado_hora) + sueldo_base=sueldo_hora_base_empleado_sin_experiencia+bono_por_buen_empleado + plus_por_experiencia=sueldo_hora_base_empleado_sin_experiencia*habilidad_empleados[i] + sueldo_semanal_empleado.append(int(math.ceil((sueldo_base+plus_por_experiencia)*dedicacion_diaria_diponible_empleado[i]))) + + for i in range(0,cantidad_tareas): + esfuerzo_requerido_tarea.append(random.randint(menor_duracion_horas_tarea,mayor_duracion_horas_tarea)) + + ###################### + #calculo del deadline + ###################### + + + tiempo_ocupado_empleado = {} + for indice_empleado in range(0,cantidad_empleados): + tiempo_ocupado_empleado[indice_empleado]=0 + + tiempo_en_horas=0 + tiempo_en_dias_con_decimales=0 + indice_empleado_menor_tiempo=0 + for indice_tarea in range(0,cantidad_tareas): + minimo_tiempo=sys.float_info.max + for indice_empleado in range(0,cantidad_empleados): + tiempo_en_horas=(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias_con_decimales= tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado] + tiempo_en_el_que_termina_si_se_le_da_esta_tarea=tiempo_ocupado_empleado[indice_empleado]+tiempo_en_dias_con_decimales + if(tiempo_en_el_que_termina_si_se_le_da_esta_tarea < minimo_tiempo): + indice_empleado_menor_tiempo=indice_empleado + minimo_tiempo=tiempo_en_el_que_termina_si_se_le_da_esta_tarea + tiempo_ocupado_empleado[indice_empleado_menor_tiempo]=minimo_tiempo + + + deadline_dias=0 + #busca maxima duracion + for indice_empleado in range(0,cantidad_empleados): + if(tiempo_ocupado_empleado[indice_empleado]>deadline_dias): + deadline_dias=tiempo_ocupado_empleado[indice_empleado] + + #print tiempo_ocupado_empleado + #se redondean los dias para pagar el dia entero a los que trabajan menos + deadline_dias=int(math.ceil(deadline_dias))*1.2 + + #archivo de salida de empleados + archivo = open ("%s_empleados"%archivo_salida, "w") + archivo.write("e%d"%1) + for i in range(1,cantidad_empleados): + #nombre del empleado + archivo.write(" e%d"%(i+1)) + archivo.write("\n") + archivo.write("%d"%dedicacion_diaria_diponible_empleado[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %d"%dedicacion_diaria_diponible_empleado[i]) + archivo.write("\n") + archivo.write("%.2f"%habilidad_empleados[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %.2f"%habilidad_empleados[i]) + archivo.write("\n") + archivo.write("%d"%sueldo_semanal_empleado[0]) + for i in range(1,cantidad_empleados): + archivo.write(" %d"%sueldo_semanal_empleado[i]) + + #archivo de salida de tareas + archivo = open ("%s_tareas"%archivo_salida, "w") + archivo.write("%d"%deadline_dias) + archivo.write("\n") + archivo.write("t%d"%1) + for i in range(1,cantidad_tareas): + #nombre de la tarea + archivo.write(" t%d"%(i+1)) + archivo.write("\n") + archivo.write("%d"%esfuerzo_requerido_tarea[0]) + for i in range(1,cantidad_tareas): + archivo.write(" %d"%esfuerzo_requerido_tarea[i]) + + + #archivo cantidad de tareas + archivo = open ("%s_cantidad_tareas"%archivo_salida, "w") + archivo.write("%d"%cantidad_tareas) + + #archivo cantidad de trabajos + archivo = open ("%s_cantidad_empleados"%archivo_salida, "w") + archivo.write("%d"%cantidad_empleados) + + +except IOError as error: + print error diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.cfg b/ProyectoFinal/CHC/malva/rep/GA/newGA.cfg new file mode 100644 index 0000000..c7caf7a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/newGA.cfg @@ -0,0 +1,18 @@ +10 // number of independent runs +100 // number of generations +60 // number of individuals +100 // size of offsprings in each generation +1 // if replaces parents for offsprings, or only offsprings may be new parents +1 // display state ? +Selections // selections to apply +1 3 // selection of parents +2 0 // selection of offsprings +Intra-Operators // operators to apply in the population +0 0.6 // crossover & its probability +1 1.0 0.01 // mutation & its probability +Inter-Operators // operators to apply between this population and anothers +0 10 5 1 3 1 5 // operator number, operator rate, number of individuals, selection of indidivual to send and remplace +LAN-configuration +1 // refresh global state +0 // 0: running in asynchronized mode / 1: running in synchronized mode +1 // interval of generations to check solutions from other populations diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.hh b/ProyectoFinal/CHC/malva/rep/GA/newGA.hh new file mode 100644 index 0000000..552b264 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/newGA.hh @@ -0,0 +1,868 @@ +/********************************************************************************************************* +*** *** +*** new Genetic Algorithm Skeleton v1.5 *** +*** Developed by: Gabriel Jesús Luque Polo *** +*** Last Update: 27-01-2003 *** +*** *** +*** tabular size = 4 *** +**********************************************************************************************************/ + +#ifndef INC_newGA +#define INC_newGA +#include "newGAstructures.hh" + +skeleton newGA +{ +// Si se definen más de 5 nuevos operadores por parte del usuario, se debe cambiar esta constante. +#define MAX_OP_USER 5 +// Si se algún operador tiene más de 5 parámetros se debe modificar esta variable +#define MAX_PROB_PER_OP 5 + + provides class SetUpParams; + provides class Statistics; + provides class Population; + provides class Inter_Operator; + provides class Migration; + provides class Selection; + provides class Selection_Tournament; + provides class Selection_Roulette_Wheel; + provides class Selection_Rank; + provides class Selection_Best; + provides class Selection_Worst; + provides class Operator_Pool; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + provides class StopCondition; + + requires class Problem; + requires class Solution; + requires class UserStatistics; + requires class Intra_Operator; + requires class Crossover; + requires class Mutation; + requires class StopCondition_1; + requires bool terminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem(); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int cantDias() const; + int cantEmpleados() const; + int dimension() const; + + Empleado * empleados() const; + int * tareasEsf() const; + int * tareasIndex() const; + int ** limite_barrios() const; + const char* getfield(char* line, int num); + + private: + int _cantDias; + Empleado * _empleados; + int * _tareasEsf; + int * _tareasIndex; + int _cantEmpleados; + int _dimension; + int ** _limite_barrios; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness (); + unsigned int size() const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + unsigned long nb_evaluation_best_found_trial; + unsigned long nb_iteration_best_found_trial; + double best_cost_trial; + double worst_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Intra_Operator ( clase abstracta ) -------------------------------------------------------------- + + requires class Intra_Operator + { + protected: + unsigned int _number_operator; + float *probability; + + public: + Intra_Operator(const unsigned int _number_op); + virtual ~Intra_Operator(); + + static Intra_Operator *create(const unsigned int _number_op); + friend ostream& operator<< (ostream& os, const Intra_Operator& intra); + + virtual void execute(Rarray<Solution*>& sols) const=0; + virtual void setup(char line[MAX_BUFFER]) = 0; + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const=0; + virtual void UpdateFromState(const StateCenter& _sc)=0; + }; + +// Crossover ---------------------------------------------------------------------------------- + + requires class Crossover: public Intra_Operator + { + public: + Crossover(); + virtual ~Crossover(); + + friend ostream& operator << (ostream& os, const Crossover& cross); + + void cross(Solution &sol1,Solution &sol2) const; + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Mutation ---------------------------------------------------------------------------------- + + requires class Mutation: public Intra_Operator + { + public: + Mutation(); + virtual ~Mutation(); + + friend ostream& operator<< (ostream& os, const Mutation& mutation); + + void mutate(Solution& sol) const; + // applies mutation over all solutions in array sols + virtual void execute(Rarray<Solution*>& sols) const; + virtual void setup(char line[MAX_BUFFER]); + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + + }; + +// StopCondition ---------------------------------------------------------------------------------- + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + +// StopCondition_1 {subclase------------------------------------------------------------------------- + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _nb_evolution_steps; + unsigned int _population_size; // number of individuals + unsigned int _population_additional_size; // size of offspring in each generation + bool _combine; // combines parents and offsprings to select new parents ? + bool _display_state; + + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _check_asynchronous; + + // selection of parents and offsprings + mutable unsigned int _select_parents; + mutable unsigned int _select_offsprings; + mutable unsigned int _parameter_select_parents; + mutable unsigned int _parameter_select_offsprings; + + Rlist<unsigned int> _intra_operators; + Rlist<unsigned int> _inter_operators; + + Operator_Pool& _pool; + + public: + SetUpParams (Operator_Pool& pool); + Operator_Pool& pool() const; + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long nb_evolution_steps() const; + const unsigned int population_size() const; + const unsigned int population_additional_size() const; + const bool combine() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int check_asynchronous() const; + + void independent_runs(const unsigned int val); + void nb_evolution_steps(const unsigned long val); + void population_size(const unsigned int val); + void population_additional_size(const unsigned int val); + void combine(const bool val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void check_asynchronous(const unsigned int val); + + // gets the i-th operator of inter-population + const unsigned int inter_operator_index(const unsigned int index) const; + const unsigned int inter_operators_size() const; + + // gets the i-th operator of intra-population + const unsigned int intra_operator_index(const unsigned int index) const; + const unsigned int intra_operators_size() const; + + const unsigned int select_parents() const; + const unsigned int select_offsprings() const; + const unsigned int parameter_select_parents() const; + const unsigned int parameter_select_offsprings() const; + + void select_parents(const unsigned int val); + void select_offsprings(const unsigned int val); + void parameter_select_parents(const unsigned int val); + void parameter_select_offsprings(const unsigned int val); + + void RefreshState(const StateCenter& _sc) const; + void UpdateFromState(const StateCenter& _sc) const; + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_generation; + unsigned long nb_evaluation; + double best_cost; + double global_best_cost; + double average_cost; + double standard_deviation; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + ~Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + }; + +// Population --------------------------------------------------------------------------------- + + provides class Population + { + private: + Rarray<Solution*> _parents; // individuals in population + Rarray<Solution*> _offsprings; // offsprings of current population + Rarray<Solution*> _new_parents; // individuals of previous population + Rarray<struct individual> _fitness_values; + Rarray<struct individual> _fitness_aux; + const SetUpParams& _setup; + unsigned int _upper_cost,_lower_cost; // lower and upper fitness of individuals in population + unsigned long _evaluations; + double _average_cost; + + inline void Evaluate(Solution* sols,struct individual &_f); + + public: + Population(const Problem& pbm,const SetUpParams& setup); // crea un array de objetos population; + ~Population(); + + friend ostream& operator<< (ostream& os, const Population& population); + friend istream& operator>> (istream& is, Population& population); + Population& operator= (const Population& pop); + const SetUpParams& setup() const; + void initialize(); + + // Generate a new pool of individuals in population + void evolution(); + + // interchange solutions between island + void interchange(const unsigned long current_generation, NetStream& channel); + + // creates a array with fitness of all individuals in population and its position in the population + void evaluate_parents(); + + // creates a array with fitness of all individuals and offsprings in population and its position in the population + void evaluate_offsprings(); + + // selects parents to creates offsprings + void select_parents(); + + // selects individuals for the new population + void select_offsprings(); + + const Rarray<Solution*>& parents() const; + const Rarray<Solution*>& offsprings() const; + Rarray<struct individual>& fitness_values(); + + unsigned int upper_cost() const; + unsigned int lower_cost() const; + unsigned int evaluations() const; + Solution& solution(const unsigned int index) const; + double fitness(const unsigned int index) const; + + double best_cost() const; + double worst_cost() const; + Solution& best_solution() const; + Solution& worst_solution() const; + double average_cost() const; + double standard_deviation() const; + }; + +// Inter_Operator ( abstract )----------------------------------------------------------- + + provides class Inter_Operator + { + protected: + unsigned int migration_rate; + unsigned int migration_size; + unsigned int migration_selection_1; + unsigned int migration_selection_2; + unsigned int migration_selection_conf_1; + unsigned int migration_selection_conf_2; + + unsigned int _number_operator; + const Direction direction; + + public: + Inter_Operator(const unsigned int _number_op, const Direction dir); + virtual ~Inter_Operator(); + + friend ostream& operator<< (ostream& os, const Inter_Operator& inter); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const=0; + virtual void setup(char line[MAX_BUFFER]); + unsigned int number_operator() const; + + virtual void RefreshState(const StateCenter& _sc) const; + virtual void UpdateFromState(const StateCenter& _sc); + }; + +// Migration: public Inter_Operator ----------------------------------------------------------- + + provides class Migration: public Inter_Operator + { + public: + Migration(const Direction dir); + virtual ~Migration(); + + friend ostream& operator<< (ostream& os, const Migration& migration); + + virtual void execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asyncrhonous) const; + }; + +// Selection ( Makes a random selection ) ----------------------------------------- + + provides class Selection + { + protected: + unsigned int _number_selection; + const Direction direction; + + public: + + Selection(const Direction dir); + Selection(const unsigned int _number_sel, const Direction dir); + virtual ~Selection(); + + friend ostream& operator<< (ostream& os, const Selection& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + unsigned int number_selection() const; + }; + +// Selection_Tournament --------------------------------------------------------------------------------- + + provides class Selection_Tournament: public Selection + { + public: + Selection_Tournament(const Direction dir); + virtual ~Selection_Tournament(); + + friend ostream& operator<< (ostream& os, const Selection_Tournament& sel); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tourment_size,const bool remplace) const; + }; + +// Selection_Roulette_Wheel --------------------------------------------------------------------------------- + + provides class Selection_Roulette_Wheel: public Selection + { + public: + Selection_Roulette_Wheel(const Direction); + virtual ~Selection_Roulette_Wheel(); + + friend ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const; + }; + +// Selection_Rank --------------------------------------------------------------------------------- + + provides class Selection_Rank: public Selection + { + public: + Selection_Rank(const Direction dir); + Selection_Rank(const unsigned int _number_sel, const Direction dir); + virtual ~Selection_Rank(); + + friend ostream& operator<< (ostream& os, const Selection_Rank& sel); + + virtual void prepare(Rarray<struct individual>& fitness_values,const bool remplace); // const; + virtual void reset(); + + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const; + }; + +// Selection_Best --------------------------------------------------------------------------------- + + provides class Selection_Best: public Selection_Rank + { + private: + mutable unsigned int selection_best_position; + + public: + Selection_Best(const Direction); + virtual ~Selection_Best(); + + friend ostream& operator<< (ostream& os, const Selection_Best& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Selection_Worst --------------------------------------------------------------------------------- + + provides class Selection_Worst: public Selection_Rank + { + private: + mutable unsigned int selection_worst_position; + + public: + Selection_Worst(const Direction); + virtual ~Selection_Worst(); + + friend ostream& operator<< (ostream& os, const Selection_Worst& sel); + + virtual void reset(); + virtual struct individual select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const; + }; + +// Operator_Pool ------------------------------------------------------------------------- + + // pool with all operators and selections that can be chosen in the setup file + provides class Operator_Pool + { + private: + mutable Rlist<Intra_Operator> _intra_operators; + Rlist<Selection> _selectors; + Rlist<Inter_Operator> _inter_operators; + + public: + Operator_Pool(const Problem& pbm); + ~Operator_Pool(); + + Intra_Operator& intra_operator(const unsigned int index) const; + Rlist<Intra_Operator>& intra_operators() const; + Selection& selector(const unsigned int index) const; + const Rlist<Selection>& selectors() const; + Inter_Operator& inter_operator(const unsigned int index) const; + const Rlist<Inter_Operator>& inter_operators() const; + + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Population current_population; + StateCenter _sc; + + double best_cost; + double worst_cost; + Solution best_solution; + double average_cost; + double standard_deviation; + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_evaluations; + + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_worst_cost; + State_Vble _current_average_cost; + State_Vble _current_standard_deviation; + State_Vble _current_time_spent; + + State_Vble _best_solution_trial; + State_Vble _best_cost_trial; + State_Vble _worst_cost_trial; + State_Vble _iteration_best_found_in_trial; + State_Vble _evaluations_best_found_in_trial; + State_Vble _time_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _evaluations_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _global_worst_cost; + State_Vble _time_best_found; + + State_Vble _crossover_probability; // probability of applying the operator over population + State_Vble _mutation_probability; // probability of applying the operator over population + State_Vble _user_op_probability[MAX_OP_USER]; // probabilities of user operators + State_Vble _migration_rate; + State_Vble _migration_size; + State_Vble _migration_selection_1; + State_Vble _migration_selection_2; + State_Vble _migration_selection_conf_1; + State_Vble _migration_selection_conf_2; + State_Vble _select_parents; + State_Vble _select_offsprings; + State_Vble _parameter_select_parents; + State_Vble _parameter_select_offsprings; + + State_Vble _display_state; + + + public: + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + + virtual int pid() const; + bool end_trial() const; + void end_trial(bool et); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (const unsigned long int nb_generations) =0; + virtual void run (const Population& pop,const unsigned long int nb_generations) =0; + + //Partial execution + virtual void StartUp()=0; + virtual void StartUp(const Population& pop)=0; + + virtual void DoStep()=0; + + // Statistics handling ---------------------------------------------------------------------- + + Statistics& statistics(); + UserStatistics& userstatistics (); + Population& population(); + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling --------------------------------------------------------------------------- + + void RefreshState(); + void RefreshCfgState(); + void UpdateFromState(); + void UpdateFromCfgState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + unsigned long current_evaluations() const; + Solution current_best_solution() const; + double current_best_cost() const; + double current_worst_cost() const; + double current_average_cost() const; + double current_standard_deviation() const; + float current_time_spent() const; + Solution best_solution_trial() const; + double best_cost_trial() const; + double worst_cost_trial() const; + unsigned int iteration_best_found_in_trial() const; + unsigned int evaluations_best_found_in_trial() const; + float time_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + unsigned int evaluations_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + double global_worst_cost() const; + float time_best_found() const; + int display_state() const; + + float *crossover_probability() const; + float *mutation_probability() const; + float *user_op_probability(const int index) const; + unsigned int migration_rate() const; + unsigned int migration_size() const; + unsigned int migration_selection_1() const; + unsigned int migration_selection_2() const; + unsigned int migration_selection_conf_1() const; + unsigned int migration_selection_conf_2() const; + unsigned int select_parents() const; + unsigned int select_offprings() const; + unsigned int parameter_select_parents() const; + unsigned int parameter_select_offsprings() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_evaluations(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_worst_cost(const double value); + void current_average_cost(const double value); + void current_standard_deviation(const double value); + void current_time_spent(const float value); + void best_solution_trial(const Solution& sol); + void best_cost_trial(const double value); + void worst_cost_trial(const double value); + void iteration_best_found_in_trial(const unsigned int value); + void evaluations_best_found_in_trial(const unsigned int value); + void time_best_found_trial(const float value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void evaluations_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void global_worst_cost(const double value); + void time_best_found(const float value); + void display_state(const int value); + + void crossover_probability(const float *probability); + void mutation_probability(const float *probability); + void user_op_probability(const int index,const float *probability); + void migration_rate(const unsigned int rate); + void migration_size(const unsigned int size); + void migration_selection_1(const unsigned int seleciton_1); + void migration_selection_2(const unsigned int selection_2); + void migration_selection_conf_1(const unsigned int selection_conf_1); + void migration_selection_conf_2(const unsigned int selection_conf_2); + void select_parents(const unsigned int selection); + void select_offsprings(const unsigned int selection); + void parameter_select_parents(const unsigned int value); + void parameter_select_offsprings(const unsigned int value); + + void show_state() const; + void KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_trial,const float total_time_spent); + }; + + provides class Solver_Seq: public Solver + { + public: + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + int receive_local_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + unsigned long acum_iterations; + unsigned long acum_evaluations; + + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + //Communication + void send_local_state_to(int _mypid); + void check_for_refresh_global_state(); + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + int receive_local_state(); + + unsigned int _current_trial; + unsigned long _current_iteration; + unsigned long _current_evaluations; + double _best_cost_trial; + Solution _best_solution_trial; + double _worst_cost_trial; + float _time_best_found_in_trial; + unsigned long _iteration_best_found_in_trial; + unsigned long _evaluations_best_found_in_trial; + + // Termination phase // + bool final_phase; + unsigned long acum_iterations; + unsigned long acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods ----------------------------------------------------------------------- + + // Full execution + virtual void run (); + virtual void run (const unsigned long int nb_generations); + virtual void run (const Population& pop,const unsigned long int nb_generations); + + //Partial execution + virtual void StartUp(); + virtual void StartUp(const Population& pop); + + virtual void DoStep(); + + //Communication + void send_local_state_to(int _mypid); + void check_for_refresh_global_state(); + void reset(); + }; + +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.pro.cc b/ProyectoFinal/CHC/malva/rep/GA/newGA.pro.cc new file mode 100644 index 0000000..dfdd244 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/newGA.pro.cc @@ -0,0 +1,2831 @@ +#include "newGA.hh" + +skeleton newGA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (Operator_Pool& pool) + : _independent_runs(0), + _nb_evolution_steps(0), + _population_size(0), + _population_additional_size(0), + _select_parents(0), + _select_offsprings(0), + _parameter_select_parents(0), + _parameter_select_offsprings(0), // Parameter of selection is fixed to 0 + _inter_operators(), + _intra_operators(), + _combine(1), + _refresh_global_state(1), + _synchronized(0), + _check_asynchronous(1), + _display_state(0), + _pool(pool) + {} + + Operator_Pool& SetUpParams::pool() const + { + return _pool; + } + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + long op; + int parameter; + short int nb_section=0; + short int nb_io = 0; + short int nb_selection = 0; + short int nb_param=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"Selections"))) nb_section=1; + if (!(strcmp(command,"Intra-Operators"))) nb_section=2; + if (!(strcmp(command,"Inter-Operators"))) nb_section=3; + if (!(strcmp(command,"LAN-configuration"))) nb_section=4; + + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.nb_evolution_steps(op); break; + case 2: setup.population_size(op); break; + case 3: setup.population_additional_size(op); break; + case 4: setup.combine(op); break; + case 5: setup.display_state(op); break; + } + nb_param++; + break; + case 1: op=-1; // creates the chosen selection method + parameter=0; + sscanf(buffer," %d %d",&op,¶meter); + if (nb_selection>=2) break; + assert(parameter>=0); + if (nb_selection==0) + { + setup.select_parents(op); + setup.parameter_select_parents(parameter); + } + else + { + setup.select_offsprings(op); + setup.parameter_select_offsprings(parameter); + } + nb_selection++; + break; + case 2: setup.pool().intra_operators().append(Intra_Operator::create(op)); + setup.pool().intra_operator(nb_io).setup(buffer); + setup._intra_operators.append(new unsigned int(nb_io)); + nb_io++; + break; + case 3: setup._inter_operators.append(new unsigned int(op)); + setup.pool().inter_operator(op).setup(buffer); + break; + case 4: if (nb_LAN_param>=3) break; + switch (nb_LAN_param) + { + case 0: setup.refresh_global_state(op); break; + case 1: setup.synchronized(op); break; + case 2: assert(op>0); + setup.check_asynchronous(op); break; + } + nb_LAN_param++; + break; + } + } + + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evolution steps: " << setup.nb_evolution_steps() << endl + << "\t" << "Size of Population: " << setup.population_size() << endl + << "\t" << "Size of Additional population: " << setup.population_additional_size() << endl; + if (setup.combine()) + os << "\t" <<"With combination between parents and offsprings" << endl; + else + os << "\t" <<"Without combination between parents and offsprings" << endl; + + os << "\t" << "Display State: " << setup.display_state() << endl << endl + << "\t" << "Selections:" << endl + << "\t" << "-----------" << endl << endl + << "\t" << "Selection parents -> " << setup.pool().selector(setup.select_parents()) << endl + << "\t" << "Parameter of selection: " << setup.parameter_select_parents() << endl + << "\t" << "Selection offsprings -> " << setup.pool().selector(setup.select_offsprings()) << endl + << "\t" << "Parameter of selection: " << setup.parameter_select_offsprings() << endl << endl + << "\t" << "Intra_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.intra_operators_size();i++) + os << "\t" << (setup.pool().intra_operator(setup.intra_operator_index(i))) << endl; + + os << endl << "\t" << "Inter_Operators: " << endl + << "\t" << "-----------" << endl << endl; + + for (int i=0;i<setup.inter_operators_size();i++) + os << "\t" << "Operator: " << setup.pool().inter_operator(setup.inter_operator_index(i)) << endl; + + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + os << "\t" << "Interval for checking asynchronous receptions: " << setup.check_asynchronous() << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::nb_evolution_steps() const + { + return _nb_evolution_steps; + } + + const unsigned int SetUpParams::population_size() const + { + return _population_size; + } + + const unsigned int SetUpParams::population_additional_size() const + { + return _population_additional_size; + } + + const bool SetUpParams::combine() const + { + return _combine; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::check_asynchronous() const + { + return _check_asynchronous; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs=val; + } + + void SetUpParams::nb_evolution_steps(const unsigned long val) + { + _nb_evolution_steps=val; + } + + void SetUpParams::population_size(const unsigned int val) + { + _population_size=val; + } + + void SetUpParams::population_additional_size(const unsigned int val) + { + _population_additional_size=val; + } + + void SetUpParams::combine(const bool val) + { + _combine=val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::check_asynchronous(const unsigned int val) + { + _check_asynchronous=val; + } + + const unsigned int SetUpParams::select_parents() const + { + return _select_parents; + } + + const unsigned int SetUpParams::select_offsprings() const + { + return _select_offsprings; + } + + const unsigned int SetUpParams::parameter_select_parents() const + { + return _parameter_select_parents; + } + + const unsigned int SetUpParams::parameter_select_offsprings() const + { + return _parameter_select_offsprings; + } + + void SetUpParams::select_parents(const unsigned int val) + { + _select_parents=val; + } + + void SetUpParams::select_offsprings(const unsigned int val) + { + _select_offsprings=val; + } + + void SetUpParams::parameter_select_parents(const unsigned int val) + { + _parameter_select_parents=val; + } + + void SetUpParams::parameter_select_offsprings(const unsigned int val) + { + _parameter_select_offsprings=val; + } + + const unsigned int SetUpParams::intra_operator_index(const unsigned int index) const + { + return _intra_operators[index]; + } + + const unsigned int SetUpParams::intra_operators_size() const + { + return _intra_operators.size(); + } + + const unsigned int SetUpParams::inter_operator_index(const unsigned int index) const + { + return _inter_operators[index]; + } + + const unsigned int SetUpParams::inter_operators_size() const + { + return _inter_operators.size(); + } + + void SetUpParams::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_select_parents",(char *)&_select_parents,1,sizeof(_select_parents)); + _sc.set_contents_state_variable("_parameter_select_parents",(char *)&_parameter_select_parents,1,sizeof(_parameter_select_parents)); + _sc.set_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,1,sizeof(_select_offsprings)); + _sc.set_contents_state_variable("_parameter_select_offsprings",(char *)&_parameter_select_offsprings,1,sizeof(_parameter_select_offsprings)); + _sc.set_contents_state_variable("_display_state",(char *)&_display_state,1,sizeof(bool)); + } + + void SetUpParams::UpdateFromState(const StateCenter& _sc) const + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_select_parents",(char *)&_select_parents,nbytes,length); + _sc.get_contents_state_variable("_parameter_select_parents",(char *)&_parameter_select_parents,nbytes,length); + _sc.get_contents_state_variable("_select_offsprings",(char *)&_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_parameter_select_offsprings",(char *)&_parameter_select_offsprings,nbytes,length); + _sc.get_contents_state_variable("_display_state",(char *)&_display_state,nbytes,length); + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Trial: " << stats.stats_data[i].trial + << " Generation: " << stats.stats_data[i].nb_generation + << " Evaluation: " << stats.stats_data[i].nb_evaluation + << " Current best cost: " << stats.stats_data[i].best_cost + << " Global best cost: " << stats.stats_data[i].global_best_cost + << " Avg: " << stats.stats_data[i].average_cost + << " Std. Dev.: " << stats.stats_data[i].standard_deviation; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + struct stat *new_stat=(struct stat *)malloc(sizeof(struct stat)); + + new_stat->trial=solver.current_trial(); + new_stat->nb_generation=solver.current_iteration(); + new_stat->nb_evaluation=solver.current_evaluations(); + new_stat->average_cost=solver.current_average_cost(); + new_stat->standard_deviation=solver.current_standard_deviation(); + new_stat->best_cost=solver.current_best_cost(); + new_stat->global_best_cost=solver.global_best_cost(); + + stats_data.append(*new_stat); + } + + void Statistics::clear() + { + stats_data.remove(); + } + + Statistics::~Statistics() + {} + +// Population ------------------------------------------------------ + + Population::Population(const Problem& pbm,const SetUpParams& setup) + :_parents(setup.population_size()), + _fitness_values(setup.population_size()), + _new_parents(setup.population_size()), + _offsprings(setup.population_additional_size()), + _setup(setup), + _evaluations(0) + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]=new Solution(pbm); + _new_parents[i]=new Solution(pbm); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + for (int i=0;i<_offsprings.size();i++) + _offsprings[i]=new Solution(pbm); + + } + + void Population::Evaluate(Solution* sols,struct individual &_f) + { + if(_f.change) + { + _f.change = false; + _f.fitness = sols->fitness(); + _evaluations++; + } + } + + Population& Population::operator= (const Population& pop) + { + for (int i=0;i<_parents.size();i++) + { + *_parents[i]=*((pop.parents())[i]); + _fitness_values[i] = pop._fitness_values[i]; + _evaluations = pop._evaluations; + } + return (*this); + } + + istream& operator>> (istream& is, Population& population) + { + return is; + } + + ostream& operator<< (ostream& os, const Population& population) + { + os << "---------------------------------------------------------------" << endl; + os << " PRESENT POPULATION " << endl << endl; + for (int i=0;i<population._parents.size();i++) + os << *population._parents[i] << endl; + os << endl << "---------------------------------------------------------------" << endl; + return os; + } + + const SetUpParams& Population::setup() const + { + return _setup; + } + + void Population::initialize() + { + for (int i=0;i<_parents.size();i++) + { + _parents[i]->initialize(); + _fitness_values[i].index = i; + _fitness_values[i].change = true; + } + evaluate_parents(); + } + + void Population::evaluate_parents() + { + double upper_fitness=(infinity() * (-1)); + double lower_fitness=(infinity()); + double current_fitness; + double cost=0.0; + + for (int i=0;i<_fitness_values.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + current_fitness = _fitness_values[i].fitness; + + if (current_fitness > upper_fitness ) + { + _upper_cost=i; + upper_fitness = current_fitness; + } + + if (current_fitness < lower_fitness ) + { + _lower_cost=i; + lower_fitness = current_fitness; + } + + cost += current_fitness; + } + + _average_cost = cost / _fitness_values.size(); + } + + void Population::evaluate_offsprings() + { + int i=0; + if (_setup.combine()) // new individuals selected between current individuals and offsprings + { + _fitness_aux=Rarray<struct individual>(_parents.size() + _offsprings.size()); + for (i=0;i<_parents.size();i++) + { + Evaluate(_parents[_fitness_values[i].index],_fitness_values[i]); + _fitness_aux[i] = _fitness_values[i]; + } + + for (int j=i;(j-i)<_offsprings.size();j++) + { + _fitness_aux[j].index=j; + _fitness_aux[j].change=true; + Evaluate(_offsprings[j-i],_fitness_aux[j]); + } + } + else // new individuals selected only between offsprings + { + _fitness_aux=Rarray<struct individual>(_offsprings.size()); + for (i=0;i<_offsprings.size();i++) + { + _fitness_aux[i].index=i; + _fitness_aux[i].change=true; + Evaluate(_offsprings[i],_fitness_aux[i]); + } + } + } + + void Population::evolution() + { + select_parents(); // selects individuals to apply operators + + // apply selected operators + for (int i=0;i<_setup.intra_operators_size();i++) + _setup.pool().intra_operator(_setup.intra_operator_index(i)).execute(_offsprings); + + evaluate_offsprings(); + select_offsprings(); // selects new individuals + evaluate_parents(); // calculates fitness of new individuals + } + + void Population::interchange(const unsigned long current_generation, NetStream& channel) + { + // apply selected operators + for (int i=0;i<_setup.inter_operators_size();i++) + _setup.pool().inter_operator(_setup.inter_operator_index(i)).execute((*this),current_generation,channel,_setup.synchronized(),_setup.check_asynchronous()); + } + + void Population::select_parents() + { + _setup.pool().selector(_setup.select_parents()).prepare(_fitness_values,false); + struct individual ind; + for (int i=0;i<_offsprings.size();i++) + { + ind = _setup.pool().selector(_setup.select_parents()).select_one(_parents,_offsprings,_fitness_values,_setup.parameter_select_parents(),false); + *_offsprings[i] = *_parents[ind.index]; + } + } + + void Population::select_offsprings() + { + _setup.pool().selector(_setup.select_offsprings()).prepare(_fitness_aux,false); + const int ps = _parents.size(); + Rarray<struct individual> aux(ps); + + for (int i=0;i<ps;i++) + { + if (_setup.combine()) + { + aux[i] = _setup.pool().selector(_setup.select_offsprings()).select_one(_parents,_offsprings,_fitness_aux,_setup.parameter_select_offsprings(),false); + if(aux[i].index < ps) + { + *_new_parents[i] = *_parents[aux[i].index]; + aux[i].index = i; + } + else + { + *_new_parents[i] = *_offsprings[aux[i].index-ps]; + aux[i].index = i; + } + } + else + { + aux[i]=_setup.pool().selector(_setup.select_offsprings()).select_one(_offsprings,_offsprings,_fitness_aux,_setup.parameter_select_offsprings(),false); + *_parents[i] = *_offsprings[aux[i].index]; + aux[i].index = i; + } + } + + if (_setup.combine()) // interchanges current and new parents in the population + { + Solution *interchange; + for (int i=0;i<ps;i++) + { + interchange=_parents[i]; + _parents[i]=_new_parents[i]; // interchanges pointers to solutions ( NO solutions !! ) + _new_parents[i]=interchange; + } + } + for (int i=0;i<ps;i++) + { + _fitness_values[i] = aux[i]; + } + } + + const Rarray<Solution*>& Population::parents() const + { + return _parents; + } + + const Rarray<Solution*>& Population::offsprings() const + { + return _offsprings; + } + + Rarray<struct individual>& Population::fitness_values() + { + return _fitness_values; + } + + unsigned int Population::upper_cost() const + { + return _upper_cost; + } + + unsigned int Population::lower_cost() const + { + return _lower_cost; + } + + unsigned int Population::evaluations() const + { + return _evaluations; + } + + double Population::best_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_lower_cost].fitness; + else + return _fitness_values[_upper_cost].fitness; + } + + double Population::worst_cost() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return _fitness_values[_upper_cost].fitness; + else + return _fitness_values[_lower_cost].fitness; + } + + Solution& Population::best_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_lower_cost].index]; + else + return *_parents[_fitness_values[_upper_cost].index]; + } + + Solution& Population::worst_solution() const + { + if ((*_parents[0]).pbm().direction() == minimize) + return *_parents[_fitness_values[_upper_cost].index]; + else + return *_parents[_fitness_values[_lower_cost].index]; + } + + Solution& Population::solution(const unsigned int index) const + { + return *_parents[index]; + } + + double Population::fitness(const unsigned int index) const + { + return _fitness_values[index].fitness; + } + + double Population::average_cost() const + { + return _average_cost; + } + + double Population::standard_deviation() const + { + double standard=0.0; + for (int i=0;i<_fitness_values.size();i++) + standard += pow ((_fitness_values[i].fitness - _average_cost),2); + standard=sqrt(standard / (_fitness_values.size()-1)); + return standard; + } + + Population::~Population() + { + for (int i=0;i<_parents.size();i++) + delete(_parents[i]); + for (int i=0;i<_offsprings.size();i++) + delete(_offsprings[i]); + for (int j=0;j<_new_parents.size();j++) + delete(_new_parents[j]); + } + + +// Inter_operator ------------------------------------------------------------------- + + Inter_Operator::Inter_Operator(const unsigned int _number_op,const Direction dir): + _number_operator(_number_op), + direction(dir), + migration_rate(1), + migration_size(1), + migration_selection_1(0), + migration_selection_2(0), + migration_selection_conf_1(0), + migration_selection_conf_2(0) + {} + + unsigned int Inter_Operator::number_operator() const + { + return _number_operator; + } + + void Inter_Operator::setup(char line[MAX_BUFFER]) + { + int op; + int new_migration_rate=1; + int new_migration_size=1; + int new_migration_selection_1=0; + int new_migration_selection_conf_1=0; + int new_migration_selection_2=0; + int new_migration_selection_conf_2=0; + + sscanf(line," %d %d %d %d %d %d %d ",&op,&new_migration_rate,&new_migration_size,&new_migration_selection_1,&new_migration_selection_conf_1,&new_migration_selection_2,&new_migration_selection_conf_2); + + assert(new_migration_rate>0); + assert(new_migration_size>0); + assert(new_migration_selection_1>=0); + assert(new_migration_selection_conf_1>=0); + assert(new_migration_selection_2>=0); + assert(new_migration_selection_conf_2>=0); + + migration_rate=new_migration_rate; + migration_size=new_migration_size; + migration_selection_1=new_migration_selection_1; + migration_selection_conf_1=new_migration_selection_conf_1; + migration_selection_2=new_migration_selection_2; + migration_selection_conf_2=new_migration_selection_conf_2; + } + + void Inter_Operator::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_migration_rate",(char *)&migration_rate,1,sizeof(migration_rate)); + _sc.set_contents_state_variable("_migration_size",(char *)&migration_size,1,sizeof(migration_size)); + _sc.set_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,1,sizeof(migration_selection_1)); + _sc.set_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,1,sizeof(migration_selection_2)); + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,1,sizeof(migration_selection_conf_1)); + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,1,sizeof(migration_selection_conf_2)); + } + + void Inter_Operator::UpdateFromState(const StateCenter& _sc) + { + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&migration_rate,nitems,length); + _sc.get_contents_state_variable("_migration_size",(char *)&migration_size,nitems,length); + _sc.get_contents_state_variable("_migration_selection_1",(char *)&migration_selection_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_2",(char *)&migration_selection_2,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&migration_selection_conf_1,nitems,length); + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&migration_selection_conf_2,nitems,length); + } + + ostream& operator<< (ostream& os, const Inter_Operator& inter) + { + switch (inter.number_operator()) + { + case 0: os << (Migration&)inter;break; + } + return os; + } + + Inter_Operator::~Inter_Operator() + {} + +// Migration ------------------------------------------------------------ + + Migration::Migration(const Direction dir):Inter_Operator(0,dir) + {} + + void Migration::execute(Population& pop,const unsigned long current_generation,NetStream& _netstream,const bool synchronized,const unsigned int check_asynchronous) const + { + + Solution* solution_to_send; + Solution* solution_received; + Solution* solution_to_remplace; + bool need_to_revaluate=false; + int mypid; + + int nb_proc=_netstream.pnumber(); // Get the number of processes running + + mypid=_netstream.my_pid(); + + int to = (mypid + 1) % nb_proc; // Source (from) and Target (to) of processes + int from = (nb_proc + mypid - 1) % nb_proc; + + // process number 0 is only to store the global state + if (to==0) to=1; + if (from==0) from=nb_proc - 1; + + _netstream << set_target(to) << set_source(from) + << get_target(&to) << get_source(&from); + + if ( (current_generation % migration_rate) == 0 + && (current_generation!=pop.setup().nb_evolution_steps())) // in this generation this operator have to be applied + { + pop.setup().pool().selector(migration_selection_1).prepare(pop.fitness_values(),false); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to send + solution_to_send = pop.parents()[pop.setup().pool().selector(migration_selection_1).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_1,false).index]; + + _netstream << *solution_to_send; + } + _netstream << pack_end; + + if (synchronized) // synchronous mode: blocked until data are received + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << set_source(MPI_ANY_SOURCE); + int tipo = 0; + _netstream._wait2(any,tipo); + + if (tipo == 1){ + return; + } + + _netstream << wait(packed); + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } + _netstream << pack_end; + + } + } // end if + + if (!synchronized && ((current_generation % check_asynchronous) ==0)) + { // asynchronous mode: if there are not data, continue; + // but, if there are data, i have to receive it + int pending=false; + _netstream._probe(packed,pending); + if (pending) + { + pop.setup().pool().selector(migration_selection_2).prepare(pop.fitness_values(),true); + + _netstream << pack_begin; + for (int i=0;i<migration_size;i++) + { + pending=false; + _netstream._probe(regular,pending); + if (!pending) break; + + // select individual to be remplaced + struct individual ind; + ind = pop.setup().pool().selector(migration_selection_2).select_one( + pop.parents(),pop.offsprings(),pop.fitness_values(),migration_selection_conf_2,true); + solution_to_remplace = pop.parents()[ind.index]; + solution_received=new Solution(solution_to_remplace->pbm()); + _netstream >> *solution_received; + + // remplace policy + if ((solution_received->fitness()<=solution_to_remplace->fitness() && direction==minimize) + || (solution_received->fitness()>=solution_to_remplace->fitness() && direction==maximize)) + { + need_to_revaluate=true; + for(int j = 0; j < pop.parents().size(); j++) + { + if(pop.fitness_values()[j].index == ind.index) + { + pop.fitness_values()[j].change = true; + *pop.parents()[ind.index] = *solution_received; + } + } + } + delete(solution_received); + } // end for + _netstream << pack_begin; + } // end if + } + + if (need_to_revaluate) pop.evaluate_parents(); + } + + ostream& operator<< (ostream& os, const Migration& migration) + { + os << "Migration." + << endl << "\t" << " Rate: " << migration.migration_rate + << endl << "\t" << " Size: " << migration.migration_size + << endl << "\t" << " Selection 1: " << migration.migration_selection_1 + << endl << "\t" << " Selection 1 Parameter: " << migration.migration_selection_conf_1 + << endl << "\t" << " Selection 2: " << migration.migration_selection_2 + << endl << "\t" << " Selection 2 Parameter: " << migration.migration_selection_conf_2; + return os; + } + + Migration::~Migration() + {} + +// Selection ------------------------------------------------------------ + + Selection::Selection(const Direction dir):_number_selection(0),direction(dir) + {} + + Selection::Selection(const unsigned int _number_sel, const Direction dir):_number_selection(_number_sel),direction(dir) + {} + + void Selection::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + {} + + struct individual Selection::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy,const bool remplace) const + { // select a random individual + return fitness_values[rand_int(0,fitness_values.size()-1)]; + } + + unsigned int Selection::number_selection() const + { + return _number_selection; + } + + ostream& operator<< (ostream& os, const Selection& sel) + { + switch (sel.number_selection()) + { + case 0: os << "Random Selection"; break; + case 1: os << (Selection_Tournament&)sel; break; + case 2: os << (Selection_Roulette_Wheel&)sel; break; + case 3: os << (Selection_Rank&)sel; break; + case 4: os << (Selection_Best&)sel; break; + case 5: os << (Selection_Worst&)sel; break; + } + return os; + } + + Selection::~Selection() + {} + +// Selection_Tournament---------------------------------------------------- + + Selection_Tournament::Selection_Tournament(const Direction dir):Selection(1,dir) + {} + + struct individual Selection_Tournament::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int tournament_size, const bool remplace) const + { + unsigned int best_sol=0; + double best_fitness=((-1) * direction * infinity()); + unsigned int index; + + if (remplace) best_fitness = -1 * best_fitness; + + unsigned int new_tournament_size=tournament_size; + if (tournament_size==0) new_tournament_size=1; + + for (int i=0;i<new_tournament_size;i++) + { + index=rand_int(0,fitness_values.size()-1); + + switch (direction) + { + case (minimize): if (((!remplace) && (fitness_values[index].fitness<best_fitness)) + || ((remplace) && (fitness_values[index].fitness>best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + case (maximize): if (((!remplace) && (fitness_values[index].fitness>best_fitness)) + || ((remplace) && (fitness_values[index].fitness<best_fitness))) + { + best_sol = index; + best_fitness = fitness_values[index].fitness; + } + break; + } + } + + return fitness_values[best_sol]; + } + + ostream& operator<< (ostream& os, const Selection_Tournament& sel) + { + os << "Tournament Selection."; + return os; + } + + Selection_Tournament::~Selection_Tournament() + {} + +// Selection_Roulette_Wheel --------------------------------------------------- + + Selection_Roulette_Wheel::Selection_Roulette_Wheel(const Direction dir):Selection(2,dir) + {} + + void Selection_Roulette_Wheel::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + double overall_fitness=0.0; + + // inverts fitness values to select less fitness individuals with a high probability + if ((direction==maximize && (remplace)) || ((direction==minimize) && (!(remplace)))) + { + // fitness assigned if the fitness value is 0 in this case + double value_if_zero=DBL_MAX; + unsigned int nb_zeros=0; + + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + value_if_zero-=fitness_values[i].fitness; + else + nb_zeros++; + } + + value_if_zero=value_if_zero/nb_zeros; + + // Warning !! if fitness is 0 (1/0 ?) + for (int i=0;i<fitness_values.size();i++) + { + if (fitness_values[i].fitness!=0) + fitness_values[i].sel_parameter = (1 / fitness_values[i].fitness ); + else + fitness_values[i].sel_parameter = value_if_zero; + overall_fitness+= fitness_values[i].sel_parameter; + } + } + else + { + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = fitness_values[i].fitness; + overall_fitness+= fitness_values[i].sel_parameter; + } + + } + + if (overall_fitness>DBL_MAX) overall_fitness=DBL_MAX; + + // calculate relative fitness + double previous=0.0; + for (int i=0;i<fitness_values.size();i++) + { + fitness_values[i].sel_parameter = (fitness_values[i].sel_parameter / overall_fitness) + previous; + previous = fitness_values[i].sel_parameter; + } + } + + struct individual Selection_Roulette_Wheel::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int dummy, const bool remplace) const + { + double random_selected=rand01(); + int i=0; + + while (random_selected > fitness_values[i].sel_parameter ) + i++; + + return fitness_values[i]; + } + + ostream& operator<< (ostream& os, const Selection_Roulette_Wheel& sel) + { + os << "Roulette Wheel Selection."; + return os; + } + + Selection_Roulette_Wheel::~Selection_Roulette_Wheel() + {} + +// Selection_Rank -------------------------------------------------- + + int lessF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness < i2.fitness; + } + + int greaterF(const struct individual &i1,const struct individual &i2) + { + return i1.fitness > i2.fitness; + } + + Selection_Rank::Selection_Rank(const Direction dir):Selection(3,dir) + {} + + Selection_Rank::Selection_Rank(const unsigned int _number_sel, const Direction dir):Selection(_number_sel,dir) + {} + + void Selection_Rank::reset() + {} + + void Selection_Rank::prepare(Rarray<struct individual>& fitness_values,const bool remplace) + { + reset(); + + // sort individuals + if (((direction==maximize) && (!(remplace))) || ((direction==minimize) && (remplace))) + fitness_values.sort(greaterF); + else + fitness_values.sort(lessF); + } + + struct individual Selection_Rank::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int portion,const bool remplace) const + { + + unsigned int new_portion=portion; + if (portion==0 || portion>100) new_portion=100; + + return fitness_values[rand_int(0,(( fitness_values.size() * new_portion )/ 100)-1)]; + } + + ostream& operator<< (ostream& os, const Selection_Rank& sel) + { + os << "Rank-Ordered Selection."; + return os; + } + + Selection_Rank::~Selection_Rank() + {} + +// Selection_Best -------------------------------------------------- + + Selection_Best::Selection_Best(const Direction dir):Selection_Rank(4,dir),selection_best_position(0) + {} + + struct individual Selection_Best::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_best_position; + selection_best_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + return fitness_values[position_to_return]; + } + + void Selection_Best::reset() + { + selection_best_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Best& sel) + { + os << "Selection of best ordered individuals."; + return os; + } + + Selection_Best::~Selection_Best() + {} + +// Selection_Worst -------------------------------------------------- + + Selection_Worst::Selection_Worst(const Direction dir):Selection_Rank(5,dir),selection_worst_position(0) + {} + + struct individual Selection_Worst::select_one(const Rarray<Solution*>& to_select_1,const Rarray<Solution*>& to_select_2,const Rarray<struct individual>& fitness_values,const unsigned int position,const bool remplace) const + { + int position_to_return=position-1; + if (position_to_return<0) + { + position_to_return = selection_worst_position; + selection_worst_position++; + } + + position_to_return=(int)position_to_return % fitness_values.size(); + + int index=(fitness_values.size()-1) - position_to_return; + return fitness_values[index]; + } + + void Selection_Worst::reset() + { + selection_worst_position=0; + } + + ostream& operator<< (ostream& os, const Selection_Worst& sel) + { + os << "Selection of worst ordered individuals."; + return os; + } + + Selection_Worst::~Selection_Worst() + {} + +// Operator_Pool ------------------------------------------------------------------------ + + Operator_Pool::Operator_Pool(const Problem& pbm) + { + // introduces all operators and selections in lists + + // Index to be chosen in setup file + //------------------------------------- + // The Intra_Operators are introduced dimanicly in setup + + _selectors.append(new Selection(pbm.direction())); // 0 + _selectors.append(new Selection_Tournament(pbm.direction())); // 1 + _selectors.append(new Selection_Roulette_Wheel(pbm.direction())); // 2 + _selectors.append(new Selection_Rank(pbm.direction())); // 3 + _selectors.append(new Selection_Best(pbm.direction())); // 4 + _selectors.append(new Selection_Worst(pbm.direction())); // 5 + + _inter_operators.append(new Migration(pbm.direction())); // 0 + } + + Intra_Operator& Operator_Pool::intra_operator(const unsigned int index) const + { + assert(index < _intra_operators.size()); + return _intra_operators[index]; + } + + Rlist<Intra_Operator>& Operator_Pool::intra_operators() const + { + return _intra_operators; + } + + Selection& Operator_Pool::selector(const unsigned int index) const + { + assert(index < _selectors.size()); + return _selectors[index]; + } + + const Rlist<Selection>& Operator_Pool::selectors() const + { + return _selectors; + } + + Inter_Operator& Operator_Pool::inter_operator(const unsigned int index) const + { + assert(index < _inter_operators.size()); + return _inter_operators[index]; + } + + const Rlist<Inter_Operator>& Operator_Pool::inter_operators() const + { + return _inter_operators; + } + + Operator_Pool::~Operator_Pool() + {} + +// Solver (superclasse)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + current_population(pbm,setup), + best_cost((-1) * pbm.direction() * infinity()), + worst_cost((-1) * best_cost), + best_solution(problem), + average_cost(0.0), + standard_deviation(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_evaluations("_current_evaluations",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_worst_cost("_current_worst_cost",_sc), + _current_average_cost("_current_average_cost",_sc), + _current_standard_deviation("_current_standard_deviation",_sc), + _current_time_spent("_current_time_spent",_sc), + _best_solution_trial("_best_sol_trial",_sc), + _best_cost_trial("_best_cost_trial",_sc), + _worst_cost_trial("_worst_cost_trial",_sc), + _iteration_best_found_in_trial("_iteration_best_found_in_trial",_sc), + _evaluations_best_found_in_trial("_evaluations_best_found_in_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found",_sc), + _evaluations_best_found("_evaluations_best_found",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _global_worst_cost("_global_worst_cost",_sc), + _time_best_found("_time_best_found",_sc), + _crossover_probability("_crossover_probability",_sc), + _mutation_probability("_mutation_probability",_sc), + _migration_rate("_migration_rate",_sc), + _migration_size("_migration_size",_sc), + _migration_selection_1("_migration_selection_1",_sc), + _migration_selection_2("_migration_selection_2",_sc), + _migration_selection_conf_1("_migration_selection_conf_1",_sc), + _migration_selection_conf_2("_migration_selection_conf_2",_sc), + _select_parents("_select_parents",_sc), + _select_offsprings("_select_offsprings",_sc), + _parameter_select_parents("_parameter_select_parents",_sc), + _parameter_select_offsprings("_parameter_select_offsprings",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_evaluations(0); + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + best_solution_trial(best_solution); + best_cost_trial(best_cost); + worst_cost_trial(worst_cost); + iteration_best_found_in_trial(0); + evaluations_best_found_in_trial(0); + time_best_found_trial(time_spent_in_trial); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + evaluations_best_found(0); + global_best_solution(best_solution); + global_best_cost(best_cost); + global_worst_cost(worst_cost); + time_best_found(total_time_spent); + + float prob[MAX_PROB_PER_OP] = {0.0}; + crossover_probability(prob); + mutation_probability(prob); + + char aux[] = "_user_op_probability"; + char nombre[30]; + for(int i = 0; i < MAX_OP_USER; i++) + { + sprintf(nombre,"%s%d",aux,i); + _user_op_probability[i].set_name((char *)nombre); + _sc.add(_user_op_probability[i]); + user_op_probability(i,prob); + } + + migration_rate(0); + migration_size(0); + migration_selection_1(0); + migration_selection_2(0); + migration_selection_conf_1(0); + migration_selection_conf_2(0); + select_parents(0); + select_offsprings(0); + parameter_select_parents(0); + parameter_select_offsprings(0); + display_state(setup.display_state()); + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + void Solver::end_trial(bool et) + { + _end_trial = et; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _current_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_iteration.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_evaluations() const + { + unsigned long value=0; + unsigned long nitems,length; + _current_evaluations.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _current_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_average_cost() const + { + double value=0.0; + unsigned long nitems,length; + _current_average_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::current_standard_deviation() const + { + double value=0.0; + unsigned long nitems,length; + _current_standard_deviation.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::best_solution_trial() const + { + Solution sol(problem); + char data_stored[_best_solution_trial.get_nitems() + _best_solution_trial.get_length()]; + unsigned long nitems,length; + _best_solution_trial.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::best_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _best_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::worst_cost_trial() const + { + double value=0.0; + unsigned long nitems,length; + _worst_cost_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found_in_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found_in_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::evaluations_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _evaluations_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _global_best_solution.get_contents(data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_best_cost.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::global_worst_cost() const + { + double value=0.0; + unsigned long nitems,length; + _global_worst_cost.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _display_state.get_contents((char *)&value, nitems, length); + return value; + } + + float *Solver::crossover_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::mutation_probability() const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_mutation_probability",(char *)¤t_probability,nitems,length); + return current_probability; + } + + float *Solver::user_op_probability(const int index) const + { + float *current_probability = new float[MAX_PROB_PER_OP]; + unsigned long nitems,length; + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.get_contents_state_variable(aux,(char *)¤t_probability,nitems,length); + return current_probability; + } + + unsigned int Solver::migration_rate() const + { + unsigned int rate=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_rate",(char *)&rate,nitems,length); + return rate; + } + + unsigned int Solver::migration_size() const + { + unsigned int size=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_size",(char *)&size,nitems,length); + return size; + } + + unsigned int Solver::migration_selection_1() const + { + unsigned int selection_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_1",(char *)&selection_1,nitems,length); + return selection_1; + } + + unsigned int Solver::migration_selection_2() const + { + unsigned int selection_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_2",(char *)&selection_2,nitems,length); + return selection_2; + } + + unsigned int Solver::migration_selection_conf_1() const + { + unsigned int selection_conf_1=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,nitems,length); + return selection_conf_1; + } + + unsigned int Solver::migration_selection_conf_2() const + { + unsigned int selection_conf_2=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,nitems,length); + return selection_conf_2; + } + + unsigned int Solver::select_parents() const + { + unsigned int select_parents=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_parents",(char *)&select_parents,nitems,length); + return select_parents; + } + + unsigned int Solver::select_offprings() const + { + unsigned int select_offsprings=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_select_offsprings",(char *)&select_offsprings,nitems,length); + return select_offsprings; + } + + unsigned int Solver::parameter_select_parents() const + { + unsigned int parameter_select_parents; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_parents",(char *)¶meter_select_parents,nitems,length); + return parameter_select_parents; + } + + unsigned int Solver::parameter_select_offsprings() const + { + unsigned int parameter_select_offsprings; + unsigned long nitems,length; + _sc.get_contents_state_variable("_parameter_select_offsprings",(char *)¶meter_select_offsprings,nitems,length); + return parameter_select_offsprings; + } + + void Solver::current_trial(const unsigned int value) + { + _current_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _current_iteration.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_evaluations(const unsigned long value) + { + _current_evaluations.set_contents((char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _current_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _current_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_worst_cost(const double value) + { + _current_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_average_cost(const double value) + { + _current_average_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_standard_deviation(const double value) + { + _current_standard_deviation.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::best_solution_trial(const Solution& sol) + { + _best_solution_trial.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::best_cost_trial(const double value) + { + _best_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::worst_cost_trial(const double value) + { + _worst_cost_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::iteration_best_found_in_trial(const unsigned int value) + { + _iteration_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found_in_trial(const unsigned int value) + { + _evaluations_best_found_in_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::evaluations_best_found(const unsigned int value) + { + _evaluations_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _global_best_solution.set_contents(sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _global_best_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::global_worst_cost(const double value) + { + _global_worst_cost.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::display_state(const int value) + { + _display_state.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::crossover_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_crossover_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::mutation_probability(const float *new_probability) + { + _sc.set_contents_state_variable("_mutation_probability",(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::user_op_probability(const int index, const float *new_probability) + { + char aux[30] = "_user_op_probability"; + sprintf(aux,"%s%d",aux,index); + + _sc.set_contents_state_variable(aux,(char *)new_probability,MAX_PROB_PER_OP,sizeof(float)); + } + + void Solver::migration_rate(const unsigned int rate) + { + _sc.set_contents_state_variable("_migration_rate",(char *)&rate,1,sizeof(int)); + } + + void Solver::migration_size(const unsigned int size) + { + _sc.set_contents_state_variable("_migration_size",(char *)&size,1,sizeof(int)); + } + + void Solver::migration_selection_1(const unsigned int selection_1) + { + _sc.set_contents_state_variable("_migration_selection_1",(char *)&selection_1,1,sizeof(int)); + } + + void Solver::migration_selection_2(const unsigned int selection_2) + { + _sc.set_contents_state_variable("_migration_selection_2",(char *)&selection_2,1,sizeof(int)); + } + + void Solver::migration_selection_conf_1(const unsigned int selection_conf_1) + { + _sc.set_contents_state_variable("_migration_selection_conf_1",(char *)&selection_conf_1,1,sizeof(int)); + } + + void Solver::migration_selection_conf_2(const unsigned int selection_conf_2) + { + _sc.set_contents_state_variable("_migration_selection_conf_2",(char *)&selection_conf_2,1,sizeof(int)); + } + + void Solver::select_parents(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_parents",(char *)&selection,1,sizeof(int)); + } + + void Solver::select_offsprings(const unsigned int selection) + { + _sc.set_contents_state_variable("_select_offsprings",(char *)&selection,1,sizeof(int)); + } + + void Solver::parameter_select_parents(const unsigned int value) + { + _sc.set_contents_state_variable("_parameter_select_parents",(char *)&value,1,sizeof(int)); + } + + void Solver::parameter_select_offsprings(const unsigned int value) + { + _sc.set_contents_state_variable("_parameter_select_offsprings",(char *)&value,1,sizeof(int)); + } + + Statistics& Solver::statistics() + { + return _stat; + } + + UserStatistics& Solver::userstatistics() + { + return _userstat; + } + + Population& Solver::population() + { + return current_population; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& best_sol,const double best_cost,const double worst_cost,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool worseG=false; + bool betterT=false; + bool worseT=false; + + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost > global_worst_cost()); + betterT = (best_cost < best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost > worst_cost_trial()); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_spent_in_trial < time_best_found())); + worseG = (worst_cost < global_worst_cost()); + betterT = (best_cost > best_cost_trial() || (best_cost == best_cost_trial() && time_spent_in_trial < time_best_found_trial())); + worseT = (worst_cost < worst_cost_trial()); + break; + } + + if (betterT) + { + best_solution_trial(best_sol); + best_cost_trial(best_cost); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_in_trial(current_iteration()); + evaluations_best_found_in_trial(current_evaluations()); + if (betterG) + { + global_best_solution(best_sol); + global_best_cost(best_cost); + time_best_found(time_spent_in_trial); + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + evaluations_best_found(current_evaluations()); + } + } + + if (worseT) + { + worst_cost_trial(worst_cost); + if (worseG) + global_worst_cost(worst_cost); + } + } + + StateCenter *Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_best_solution(best_solution); + current_best_cost(best_cost); + current_worst_cost(worst_cost); + current_average_cost(average_cost); + current_standard_deviation(standard_deviation); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::RefreshCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).RefreshState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).RefreshState(_sc); + params.RefreshState(_sc); + } + + void Solver::UpdateFromState() + { + best_solution=current_best_solution(); + best_cost=current_best_cost(); + worst_cost=current_worst_cost(); + average_cost=current_average_cost(); + standard_deviation=current_standard_deviation(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + KeepHistory(best_solution,best_cost,worst_cost,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromCfgState() + { + for (int i=0;i<params.pool().intra_operators().size();i++) + params.pool().intra_operator(i).UpdateFromState(_sc); + for (int i=0;i<params.pool().inter_operators().size();i++) + params.pool().inter_operator(i).UpdateFromState(_sc); + params.UpdateFromState(_sc); + } + + void Solver::show_state() const + { + cout << endl << " Current State ---------------------------------------------" << endl; +/* cout << endl << "Selection parents -> " << select_parents(); + cout << endl << "Parameter of selection: " << parameter_select_parents(); + cout << endl << "Selection offsprings -> " << select_offprings(); + cout << endl << "Parameter of selection: " << parameter_select_offsprings() << endl; + cout << endl << "Crossover_probability: " << crossover_probability(); + cout << endl << "Mutation_probability: " << mutation_probability(); + cout << endl << "User_Operator_probability: " << user_op_probability(0); + cout << endl << "Migration_rate: " << migration_rate(); + cout << endl << "Migration_size: " << migration_size(); + cout << endl << "Migration_selection_1: " << migration_selection_1(); + cout << endl << "Migration_selection_conf_1: " << migration_selection_conf_1(); + cout << endl << "Migration_selection_2: " << migration_selection_2(); + cout << endl << "Migration_selection_conf_2: " << migration_selection_conf_2() << endl; +*/ cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current evaluations: " << current_evaluations(); + cout << endl << "Current best cost: " << current_best_cost(); + cout << endl << "Current worst cost: " << current_worst_cost(); + cout << endl << "Current Average cost: " << current_average_cost(); + cout << endl << "Current Standard Deviation: " << current_standard_deviation(); + cout << endl << endl << "Trial: "; + cout << endl << "Best cost trial: " << best_cost_trial(); + cout << endl << "Worst cost trial: " << worst_cost_trial(); + cout << endl << "Iteration best found in trial: " << iteration_best_found_in_trial(); + cout << endl << "Evaluations best found in trial: " << evaluations_best_found_in_trial(); + cout << endl << "Time best found trial: " << time_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << endl << "Global: "; + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Global worst cost: " << global_worst_cost(); + cout << endl << "Trial best found: " << trial_best_found(); + cout << endl << "Iteration best found: " << iteration_best_found(); + cout << endl << "Evaluations best found: " << evaluations_best_found(); + cout << endl << "Time best found: " << time_best_found(); +// cout << endl << endl << "Best Solution: " << endl << global_best_solution(); + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + } + +// Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Seq::StartUp(const Population& pop) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + time_best_found_trial(0.0); + + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + if( (current_iteration() % params.refresh_global_state()) == 0) + UpdateFromCfgState(); + + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Seq::run (const unsigned long int nb_generations) + { + StartUp(); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + void Solver_Seq::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + while ((current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + + } + + // Solver LAN ------------------------------------------------------------ + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Lan::StartUp(const Population& pop) + { + _netstream << barrier; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Lan::send_local_state_to(int _mypid) { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_solution_trial() + << current_best_solution() + << best_cost_trial() + << worst_cost_trial() + << time_best_found_trial() + << current_best_cost() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << pack_end; + } + + int Solver_Lan::receive_local_state() { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_solution_trial + >> best_solution + >> _best_cost_trial + >> _worst_cost_trial + >> _time_best_found_in_trial + >> best_cost + >> worst_cost + >> average_cost + >> standard_deviation + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + << pack_end; + return r_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_additional_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualizaci�n de las estad�sticas // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Lan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0),acum_iterations(0) + { + + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + // random_seed(time(0) + (mypid+1)); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Population pop(problem,params); + pop.initialize(); + StartUp(pop); + } + + void Solver_Wan::StartUp(const Population& pop) + { + _netstream << barrier; + + // Termination phase // + final_phase = false; + acum_evaluations = 0; + acum_iterations = 0; + + start_trial=_used_time(); + start_global=total_time_spent; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + current_evaluations(pop.evaluations()); + + // initialize state variables in the current trial + + Solution initial_solution(problem); + + time_spent_in_trial=0.0; + best_cost_trial((-1) * problem.direction() * infinity()); + worst_cost_trial((-1) * best_cost_trial()); + best_solution_trial(initial_solution); + iteration_best_found_in_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current_population=pop; + current_population.evaluate_parents(); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + } + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + current_population.evolution(); + current_evaluations(current_population.evaluations()); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(regular, pending); + if(pending) + final_phase = true; + //////////////////////// + + current_population.interchange(current_iteration(),_netstream); + + // gets current interesting values in the current population + + best_cost=current_population.best_cost(); + best_solution=current_population.best_solution(); + worst_cost=current_population.worst_cost(); + average_cost=current_population.average_cost(); + standard_deviation=current_population.standard_deviation(); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + // refresh state with these values + RefreshState(); + RefreshCfgState(); + + // in this iteration i have to send data about my local state to the global state + if ((int)current_iteration() % params.refresh_global_state() ==0) + { + send_local_state_to(mypid); + UpdateFromCfgState(); + } + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_evaluations() + << best_cost_trial() + << best_solution_trial() + << iteration_best_found_in_trial() + << evaluations_best_found_in_trial() + << time_best_found_trial() + << worst_cost_trial() + << current_best_cost() + << current_best_solution() + << current_worst_cost() + << current_average_cost() + << current_standard_deviation() + << pack_end; + } + + int Solver_Wan::receive_local_state() + { + int r_pid=0; + + _netstream._wait(packed); + + _netstream << pack_begin + >> r_pid + >> _current_trial + >> _current_iteration + >> _current_evaluations + >> _best_cost_trial + >> _best_solution_trial + >> _iteration_best_found_in_trial + >> _evaluations_best_found_in_trial + >> _time_best_found_in_trial + >> _worst_cost_trial + >> best_cost + >> best_solution + >> worst_cost + >> average_cost + >> standard_deviation + << pack_end; + return r_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + _netstream << set_source(MPI_ANY_SOURCE); + + while (!_end_trial) + { + received_pid=0; + received_pid=receive_local_state(); + + current_trial(_current_trial); + + // refresh the global state with received data ( a local state ) + current_iteration(_iteration_best_found_in_trial); + current_evaluations(_evaluations_best_found_in_trial); + KeepHistory(_best_solution_trial,_best_cost_trial,_worst_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + // the process that has send data has finished the current trial + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && terminateQ(problem,*this,params)) + { + acum_iterations = params.nb_evolution_steps() * nb_finalized_processes; + acum_evaluations = acum_iterations* params.population_additional_size() + + nb_finalized_processes*params.population_size(); + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << 1; + } + final_phase = true; + } + nb_finalized_processes++; + acum_iterations += _iteration_best_found_in_trial; + acum_evaluations += _evaluations_best_found_in_trial; + } + if (nb_finalized_processes==nb_proc-1) + _end_trial=true; + + current_iteration(_current_iteration); + current_evaluations(_current_evaluations); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Update Stats // Termination phase // + iteration_best_found_in_trial(acum_iterations/(_netstream.pnumber()-1)); + evaluations_best_found_in_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = best_cost_trial(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + { + iteration_best_found(iteration_best_found_in_trial()); + evaluations_best_found(evaluations_best_found_in_trial()); + } + + RefreshState(); + RefreshCfgState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.nb_evolution_steps()); + } + + void Solver_Wan::run (const unsigned long int nb_generations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Population& pop,const unsigned long int nb_generations) + { + StartUp(pop); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < nb_generations) && !(terminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + int i; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> i ; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + + } + _netstream << barrier; + } + +} + + diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.pro.o b/ProyectoFinal/CHC/malva/rep/GA/newGA.pro.o new file mode 100644 index 0000000000000000000000000000000000000000..8a79374826a57f9269ae72e0a8447080a445c8b4 GIT binary patch literal 176256 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�G)+fmTdpCWMjQv%L;MJqVt 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 Jnop6){{tn3<5mCw literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.req.cc b/ProyectoFinal/CHC/malva/rep/GA/newGA.req.cc new file mode 100644 index 0000000..653d43b --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/newGA.req.cc @@ -0,0 +1,778 @@ +#ifndef INC_REQ_newGA +#define INC_REQ_newGA +#include "newGA.hh" +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sstream> +#include <algorithm> + +skeleton newGA +{ + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0),_limite_barrios(NULL),_tareasEsf(NULL),_tareasIndex(NULL),_empleados(NULL),_cantDias(0),_cantEmpleados(0) + { + //cout << "uf6"; + } + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + + //Imprimo el arreglo con los limites de barrios + os<<"Limites de barrios: "<<endl<<endl; + for (int i=0;i<pbm._dimension;i++){ + os<<i<<": "; + int indice=0; + while (pbm._limite_barrios[i][indice]!=-1){ + os<<pbm._limite_barrios[i][indice]<<","; + indice++; + } + os<<endl; + } + os<<endl; + return os; + } + + + + istream& operator>> (istream& is, Problem& pbm) + { + + char buffer[MAX_BUFFER]; + int i; + + //is.getline(buffer,MAX_BUFFER,'\n'); + //sscanf(buffer,"%d",&pbm._dimension); + + //CARGAR DATO CANT Tareas + ifstream inFile; + inFile.open("datos_cantidad_tareas"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + string x; + getline(inFile,x); + pbm._dimension = stoi(x); + inFile.close(); + + //Pido memoria para almacenar los limites de los barrios + pbm._limite_barrios=new int *[pbm._dimension]; + for (int i=0;i<pbm._dimension;i++) + { + pbm._limite_barrios[i]=new int [10]; + for (int j=0;j<10;j++) + pbm._limite_barrios[i][j]=-1; + } + + //CARGAR DATO CANT EMPLEADOS + inFile; + inFile.open("datos_cantidad_empleados"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + //string x; + getline(inFile,x); + pbm._cantEmpleados = stoi(x); + inFile.close(); + //INICIALIZAR DATOS TAREAS ESFUERZO + pbm._tareasEsf=new int [pbm._dimension]; + for (int ii=0;ii<pbm._dimension;ii++) + { + pbm._tareasEsf[ii]=0; + } + + + //CARGAR DATOS TAREAS ESFUERZO + + inFile.open("datos_tareas"); + if (!inFile) + { + cerr << "Unable to open file datafile.txt"; + exit(1); // call system to stop + } + string line2; + getline(inFile,line2); + pbm._cantDias = stoi(line2); + getline(inFile, line2); + getline(inFile, line2); + + int n = line2.length(); + char char_array[n+1]; + int len=1; + int t=0; + int z=0; + for(int i=0; i<=line2.length(); i++) + { + if(line2[i] == ' '|| i==line2.length()) + { + string rr = line2.substr(z,len); + pbm._tareasEsf[t] = stoi(rr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + inFile.close(); + + + pbm._tareasIndex = new int[pbm._dimension]; + for (int i = 0 ; i != pbm._dimension ; i++) + { + pbm._tareasIndex[i] = i; + } + sort(pbm._tareasIndex, pbm._tareasIndex + pbm._dimension,[&](const int& a, const int& b) { return (pbm._tareasEsf[a] < pbm._tareasEsf[b]); }); + /* + for (int i = 0 ; i != pbm._dimension ; i++) + { + cout << pbm._tareasIndex[i] << " "; + } + exit(0); + */ + + //INICIALIZAR EMPLEADOS + pbm._empleados=new Empleado [pbm._cantEmpleados]; + for (int zz=0;zz<pbm._cantEmpleados;zz++) + { + + pbm._empleados[zz]._sueldo = 0; + pbm._empleados[zz]._habilidad=0; + pbm._empleados[zz]._horas=0; + } + + //CARGAS DATOS EMPLEADOS + + string line23; + inFile.open("datos_empleados"); + getline(inFile, line23); + getline(inFile, line23); + int no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._horas = stoi(rrr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._horas <<" " << pbm._empleados[1]._horas <<" " << pbm._empleados[2]._horas <<" " << pbm._empleados[3]._horas << " " << pbm._empleados[4]._horas << " " << endl; + + getline(inFile, line23); + no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + // cout << line23; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._habilidad = stof(rrr); + //cout << rrr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._habilidad <<" " << pbm._empleados[1]._habilidad <<" " << pbm._empleados[2]._habilidad <<" " << pbm._empleados[3]._habilidad << " " << pbm._empleados[4]._habilidad << " " << endl; + + getline(inFile, line23); + no = line23.length(); + char_array[n+1]; + len=1; + t=0; + z=0; + for(int i=0; i<=line23.length(); i++) + { + if(line23[i] == ' ' || i==line23.length()) + { + string rrr = line23.substr(z,len); + pbm._empleados[t]._sueldo = stoi(rrr); + //cout << rr << " "; + t=t+1; + z=i+1; + len=1; + //s.erase(i,1); + } + else len=len+1; + } + cout << pbm._empleados[0]._sueldo <<" " << pbm._empleados[1]._sueldo <<" " << pbm._empleados[2]._sueldo <<" " << pbm._empleados[3]._sueldo << " " << pbm._empleados[4]._sueldo << " " << endl; + //assert(false); + inFile.close(); + + /* + //Cargo el archivo con los limites de los barrios + FILE* stream = fopen("limite_barrios.csv", "r"); + + char line[1024]; + while (fgets(line, 1024, stream)) + { + char* tmp = strdup(line); + const char * barrio = pbm.getfield(tmp,1); + int barrio_int=atoi(barrio); + tmp = strdup(line); + const char * limite= pbm.getfield(tmp,2); + int i=0; + while (limite!=NULL) + { + pbm._limite_barrios[barrio_int-1][i]=atoi(limite)-1; + i++; + tmp = strdup(line); + limite=pbm.getfield(tmp,i+2); + } + free(tmp); + } + */ + cout<<pbm; + return is; + } + + //Funcion para leer el archivo CSV + const char* Problem::getfield(char* line, int num) + { + const char* tok; + for (tok = strtok(line, ","); + tok && *tok; + tok = strtok(NULL, ",\n")) + { + if (!--num) + return tok; + } + return NULL; + } + + int ** Problem::limite_barrios() const{ + return _limite_barrios; + } + + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + int Problem::cantEmpleados() const + { + return _cantEmpleados; + } + int Problem::cantDias() const + { + return _cantDias; + } + + int * Problem::tareasEsf() const + { + return _tareasEsf; + } + + int * Problem::tareasIndex() const + { + return _tareasIndex; + } + + Empleado *Problem::empleados() const + { + return _empleados; + } + + Problem::~Problem() + { + //Libero la memoria pedida para almacenar los limites de los barrios + for (int i=0;i<_dimension;i++) + delete [] _limite_barrios[i]; + delete [] _limite_barrios; + delete [] _empleados; + delete [] _tareasEsf; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + + //for (int i=0;i<sol.pbm().dimension();i++) + // os << " " << sol._var[i]; + stringstream ss; + + ofstream outfile("solution"); + + os << endl; + + for (int j = 0; j < sol.pbm().cantEmpleados(); j++) + { + bool found1 = false; + for (int i = 0; i < sol.pbm().dimension(); i++) + { + if (sol._var[i] == j) + { + if (!found1) + { + ss << "e" << j + 1; + found1 = true; + } + + ss << " t" << sol.pbm().tareasIndex()[i] + 1; + } + } + + if (found1) + { + ss << endl; + } + } + + outfile << ss.str(); + outfile.close(); + + os << ss.str(); + + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + for(int i = 0; i < _var.size(); i++) + if(_var[i] != sol._var[i]) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + //cout << _pbm.dimension(); + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=rand_int(0,_pbm.cantEmpleados() - 1); + //_var[i]=rand_int(0,3); + } + } + + double Solution::fitness () + { + + double fitness = 0.0; + double* horasTrabajados = new double[_pbm.cantEmpleados()]; + for (int q=0; q < _pbm.cantEmpleados(); q++) + { + horasTrabajados[q] = 0; + } + + for (int i=0;i< _pbm.dimension();i++) + { + Empleado tipo = _pbm.empleados()[_var[i]]; + double horasReq = ((double)_pbm.tareasEsf()[_pbm.tareasIndex()[i]]/(double)(0.5+tipo._habilidad)); + horasTrabajados[_var[i]] += horasReq; + + } + + + for (int j = 0; j < _pbm.cantEmpleados(); j++) + { + double diasTrabajadosTemp = (double)horasTrabajados[j] / (double)_pbm.empleados()[j]._horas; + fitness += (double)diasTrabajadosTemp * (double)_pbm.empleados()[j]._sueldo; + if (isnan(fitness)) + exit(0); + if (diasTrabajadosTemp > _pbm.cantDias()) + { + fitness += 100000; + } + } + + return fitness; + + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].worst_cost_trial + << "\t\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t\t" << userstat.result_trials[i].nb_iteration_best_found_trial + << "\t\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + void UserStatistics::update(const Solver& solver) + { + if( (solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().nb_evolution_steps()) + && !terminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial = solver.evaluations_best_found_in_trial(); + new_stat->nb_iteration_best_found_trial = solver.iteration_best_found_in_trial(); + new_stat->worst_cost_trial = solver.worst_cost_trial(); + new_stat->best_cost_trial = solver.best_cost_trial(); + new_stat->time_best_found_trial = solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// Intra_operator -------------------------------------------------------------- + + Intra_Operator::Intra_Operator(const unsigned int _number_op):_number_operator(_number_op),probability(NULL) + {} + + unsigned int Intra_Operator::number_operator() const + { + return _number_operator; + } + + Intra_Operator *Intra_Operator::create(const unsigned int _number_op) + { + switch (_number_op) + { + case 0: return new Crossover;break; + case 1: return new Mutation();break; + } + } + + ostream& operator<< (ostream& os, const Intra_Operator& intra) + { + switch (intra.number_operator()) + { + case 0: os << (Crossover&)intra;break; + case 1: os << (Mutation&)intra;break; + } + return os; + } + + Intra_Operator::~Intra_Operator() + {} + +// Crossover:Intra_operator ------------------------------------------------------------- + + Crossover::Crossover():Intra_Operator(0) + { + probability = new float[1]; + } + + void Crossover::cross(Solution& sol1,Solution& sol2) const // dadas dos soluciones de la poblacion, las cruza + { + //Usamos cruzamiento de dos puntos (2PX) + int i=0; + Rarray<int> aux(sol1.pbm().dimension()); + aux=sol2.array_var(); + + /* + if (current_time_spent() < 1000000) + { + int limit=rand_int((0,sol1.pbm().dimension()-1)); + + for (i=0;i<limit;i++) + sol2.var(i)=sol1.var(i); + for (i=0;i<limit;i++) + sol1.var(i)=aux[i]; + } + if (current_time_spent() >= 1000000) + {*/ + int limit=rand_int((sol1.pbm().dimension()/2)+1,sol1.pbm().dimension()-1); + int limit2=rand_int(0,limit-1); + + for (i=0;i<limit2;i++) + sol2.var(i)=sol1.var(i); + for (i=0;i<limit2;i++) + sol1.var(i)=aux[i]; + for (i=limit;i<sol1.pbm().dimension();i++) + sol2.var(i)=sol1.var(i); + for (i=limit;i<sol1.pbm().dimension();i++) + sol1.var(i)=aux[i]; + //} + } + + void Crossover::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i+1<sols.size();i=i+2) + if (rand01()<=probability[0]) cross(*sols[i],*sols[i+1]); + } + + ostream& operator<< (ostream& os, const Crossover& cross) + { + os << "Crossover." << " Probability: " + << cross.probability[0] + << endl; + return os; + } + + void Crossover::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_crossover_probability",(char *)probability,1,sizeof(float)); + } + + void Crossover::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_crossover_probability",(char *)probability,nbytes,length); + } + + void Crossover::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f ",&op,&probability[0]); + assert(probability[0]>=0); + } + + Crossover::~Crossover() + { + delete [] probability; + } + + // Mutation: Sub_operator ------------------------------------------------------------- + + Mutation::Mutation():Intra_Operator(1) + { + probability = new float[2]; + } + + void Mutation::mutate(Solution& sol) const + { + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability[1]) + { + //La mutacion modifica un gen aleatoriamente con probabilidad uniforme en {0,3} + int temp = rand_int(0,sol.pbm().cantEmpleados() - 1); + sol.var(i)= temp; + //sol.var(i)=rand_int(0,3); + } + } + } + + void Mutation::execute(Rarray<Solution*>& sols) const + { + for (int i=0;i<sols.size();i++) + if(rand01() <= probability[0]) mutate(*sols[i]); + } + + ostream& operator<< (ostream& os, const Mutation& mutation) + { + os << "Mutation." << " Probability: " << mutation.probability[0] + << " Probability1: " << mutation.probability[1] + << endl; + return os; + } + + void Mutation::setup(char line[MAX_BUFFER]) + { + int op; + sscanf(line," %d %f %f ",&op,&probability[0],&probability[1]); + assert(probability[0]>=0); + assert(probability[1]>=0); + } + + void Mutation::RefreshState(const StateCenter& _sc) const + { + _sc.set_contents_state_variable("_mutation_probability",(char *)probability,2,sizeof(probability)); + } + + void Mutation::UpdateFromState(const StateCenter& _sc) + { + unsigned long nbytes,length; + _sc.get_contents_state_variable("_mutation_probability",(char *)probability,nbytes,length); + } + + Mutation::~Mutation() + { + delete [] probability; + } + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + bool fin=(int) (solver.current_time_spent() - solver.time_best_found_trial()) > 20000000; + //Condicion de parada. Si el fitness es 0 terminamos la ejecucion. + //bool fin=(int)solver.best_cost_trial() == 0; + //cout << pbm.cantEmpleados(); + /*if (fin){ + //Escribo el resultado en el archivo de salida + FILE * pFile; + pFile = fopen ("asignacion_colores.csv","w"); + for (int i=0;i<pbm.dimension();i++){ + fprintf (pFile, "%d,%d\n",i+1,solver.best_solution_trial().var(i)); + } + fclose (pFile); + }*/ + //return (fin); + return fin; + + } + + StopCondition_1::~StopCondition_1() + {} + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool terminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} +#endif + diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGA.req.o b/ProyectoFinal/CHC/malva/rep/GA/newGA.req.o new file mode 100644 index 0000000000000000000000000000000000000000..b38ae8dbb12876fd40eff199783aea8c7db92186 GIT binary patch literal 65312 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 z≷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 AX#fBK literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/rep/GA/newGAstructures.hh b/ProyectoFinal/CHC/malva/rep/GA/newGAstructures.hh new file mode 100644 index 0000000..d542639 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/newGAstructures.hh @@ -0,0 +1,60 @@ +#ifndef INC_newGA_mallba_hh +#define INC_newGA_mallba_hh + + +#include <iostream> +#include <fstream> +#include <math.h> +#include <limits.h> +#include <float.h> +#include <Rlist.h> +#include <Rarray.h> +#include <Messages.h> +#include <mallba.hh> +#include <States.hh> +#include <random.hh> +#include <time.hh> +#include <netstream.hh> +#include <assert.h> + +using namespace std; + +#ifndef _INDIVIDUAL_ +#define _INDIVIDUAL_ + +struct individual // index of a individual in the population and its fitness +{ + int index; + double fitness; + double sel_parameter; + bool change; +}; +struct Empleado // index of a individual in the population and its fitness +{ + int _horas; + float _habilidad; + double _sueldo; +}; + + +/*int lessF(const struct individual &i1,const struct individual &i2) +{ + return i1.fitness < i2.fitness; +} + +int lessS(const struct individual &i1,const struct individual &i2) +{ + return i1.sel_parameter < i2.sel_parameter; +} + +int greaterF(const struct individual &i1,const struct individual &i2) +{ + return i1.fitness > i2.fitness; +} + +int greaterS(const struct individual &i1,const struct individual &i2) +{ + return i1.sel_parameter > i2.sel_parameter; +}*/ +#endif +#endif diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_empleados b/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_empleados new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_empleados @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_tareas b/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_tareas new file mode 100644 index 0000000..301160a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/res/datos_cantidad_tareas @@ -0,0 +1 @@ +8 \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/datos_empleados b/ProyectoFinal/CHC/malva/rep/GA/res/datos_empleados new file mode 100644 index 0000000..f7cc5e5 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/res/datos_empleados @@ -0,0 +1,4 @@ +e1 e2 e3 e4 e5 +4 5 5 3 3 +0.05 0.20 0.30 0.95 0.50 +120 200 210 230 180 diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/datos_tareas b/ProyectoFinal/CHC/malva/rep/GA/res/datos_tareas new file mode 100644 index 0000000..589272f --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/res/datos_tareas @@ -0,0 +1,3 @@ +20 +t1 t2 t3 t4 t5 t6 t7 t8 +16 28 11 51 2 23 43 15 diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/empty.txt b/ProyectoFinal/CHC/malva/rep/GA/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/ProyectoFinal/CHC/malva/rep/GA/res/sol.txt b/ProyectoFinal/CHC/malva/rep/GA/res/sol.txt new file mode 100644 index 0000000..94d8af3 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/res/sol.txt @@ -0,0 +1,16 @@ + +--------------------------------------------------------------- + STATISTICS OF TRIALS +------------------------------------------------------------------ + +1 10029.7 210883 1060 10 1591 14184 +2 10010.4 210882 5560 55 6233 12361 +3 10010.4 210656 4160 41 8672 14731 +4 10009.9 210921 160 1 106 9399 +5 10010.4 210807 4660 46 4349 9349 +6 10010.4 210921 760 7 657 9224 +7 10016.5 210990 3060 30 5449 11825 +8 10015.4 210452 4960 49 5341 10215 +9 10035.1 210876 5960 59 5591 9491 +10 10017.7 210873 360 3 295 9422 +------------------------------------------------------------------ diff --git a/ProyectoFinal/CHC/malva/rep/GA/solution b/ProyectoFinal/CHC/malva/rep/GA/solution new file mode 100644 index 0000000..534d0b7 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/solution @@ -0,0 +1,3 @@ +e1 t3 t1 +e3 t5 t6 t4 +e4 t8 t2 t7 diff --git a/ProyectoFinal/CHC/malva/rep/GA/verificador.py b/ProyectoFinal/CHC/malva/rep/GA/verificador.py new file mode 100644 index 0000000..0924a32 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/GA/verificador.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +import random +import math + +try: + #Sanity check + if (len(sys.argv)<4): + print "Ejecutar con la siguiente linea: ./validador <ruta_tareas> <ruta_empleados> <ruta_solucion>" + sys.exit(1) + + ruta_tareas=sys.argv[1] + ruta_empleados=sys.argv[2] + ruta_solucion=sys.argv[3] + habilidad_empleados=[] + sueldo_diario_empleado=[] + dedicacion_diaria_diponible_empleado=[] + esfuerzo_requerido_tarea=[] + nombres_tareas=[] + nombre_empleados=[] + costo_proyecto=0 + tiempo_solucion_proyecto=0 + + # se sabe que son 3 lineas + archivo_tareas=open(ruta_tareas) + lineasTareas=archivo_tareas.readlines() + deadLine=lineasTareas[0] + nombres_tareas=lineasTareas[1].strip().split(" ") + esfuerzo_requerido_tarea=lineasTareas[2].strip().split(" ") + + # se sabe que son 4 lineas + archivo_empleados=open(ruta_empleados) + lineasEmpleados=archivo_empleados.readlines() + nombre_empleados=lineasEmpleados[0].strip().split(" ") + dedicacion_diaria_diponible_empleado=lineasEmpleados[1].strip().split(" ") + habilidad_empleados=lineasEmpleados[2].strip().split(" ") + sueldo_diario_empleado=lineasEmpleados[3].strip().split(" ") + + # se convierten a entero + dedicacion_diaria_diponible_empleado = map(int, dedicacion_diaria_diponible_empleado) + sueldo_diario_empleado = map(int, sueldo_diario_empleado) + deadLine=int(deadLine) + esfuerzo_requerido_tarea = map(int, esfuerzo_requerido_tarea) + + # se convierte a float + habilidad_empleados = map(float, habilidad_empleados) + + # se levanta la solucion del archivo + matriz_solucion=[] + + archivo_solucion=open(ruta_solucion) + + solucion_empleados_tareas=[] + solucion_empleados=[] + solucion_tareas=[] + + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + if( not (empleados_tareas[0] in nombre_empleados)): + print "No existe en la instancia el empleado: " + empleados_tareas[0] + sys.exit(1) + solucion_empleados.append(empleados_tareas[0]) + for i in range(1,len(empleados_tareas)): + if( not (empleados_tareas[i] in nombres_tareas)): + print "No existe en la instancia la terea: " + empleados_tareas[i] + sys.exit(1) + solucion_tareas.append(empleados_tareas[i]) + + + for i in range(0,len(solucion_empleados)): + for j in range(i+1,len(solucion_empleados)): + if(solucion_empleados[i]==solucion_empleados[j]): + print "Empleado repetido: " + solucion_empleados[i] + sys.exit(1) + + for i in range(0,len(solucion_tareas)): + for j in range(i+1,len(solucion_tareas)): + if(solucion_tareas[i]==solucion_tareas[j]): + print "Tarea asignada más de una vez: " + solucion_tareas[i] + sys.exit(1) + + + # todas las tareas asignadas + if(len(solucion_tareas)!=len(nombres_tareas)): + print "La cantidad de tareas asignadas es distinta a la cantidad de tareas de la instancia." + sys.exit(1) + + for i in range(0,len(nombres_tareas)): + if( not (nombres_tareas[i] in solucion_tareas)): + print "Tarea no asignada " + nombres_tareas[i] + sys.exit(1) + + costo_total=0 + archivo_solucion=open(ruta_solucion) + maximo_tiempo=0 + tiempo_en_dias=0 + # se hacen los calculos con la informacion en los archivos + for line in archivo_solucion.readlines(): + empleados_tareas=line.strip().split(" ") + indice_empleado = nombre_empleados.index(empleados_tareas[0]) + tiempo_en_horas=0 + for i in range(1,len(empleados_tareas)): + indice_tarea = nombres_tareas.index(empleados_tareas[i]) + tiempo_en_horas=tiempo_en_horas+(esfuerzo_requerido_tarea[indice_tarea] / (0.5 + habilidad_empleados[indice_empleado])) + tiempo_en_dias= int(math.ceil(tiempo_en_horas/dedicacion_diaria_diponible_empleado[indice_empleado])) + costo_total=costo_total+sueldo_diario_empleado[indice_empleado]*tiempo_en_dias + if(tiempo_en_dias>maximo_tiempo): + maximo_tiempo=tiempo_en_dias + + if(maximo_tiempo<=deadLine): + # todo OK! + print costo_total,maximo_tiempo + else: + print "No cumple con el tiempo máximo de finalización ({0} > {1}).".format(maximo_tiempo, deadLine) + sys.exit(1) + +except IOError as error: + print error diff --git a/ProyectoFinal/CHC/malva/rep/Makefile b/ProyectoFinal/CHC/malva/rep/Makefile new file mode 100644 index 0000000..2b7ed15 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/Makefile @@ -0,0 +1,6 @@ +all: + (cd CHC ; make) + (cd GA ; make) +clean: + (cd CHC ; make clean) + (cd GA ; make clean) \ No newline at end of file diff --git a/ProyectoFinal/CHC/malva/rep/SA/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/Config.cfg new file mode 100644 index 0000000..c515435 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +Instance Problem Path +Result File Path diff --git a/ProyectoFinal/CHC/malva/rep/SA/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/MainWan.cc b/ProyectoFinal/CHC/malva/rep/SA/MainWan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/MainWan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/Makefile b/ProyectoFinal/CHC/malva/rep/SA/Makefile new file mode 100644 index 0000000..43b74fa --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan MainWan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/instance.txt res/res.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/SA.cfg new file mode 100644 index 0000000..290f7e9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/SA.cfg @@ -0,0 +1,9 @@ + // number of independent runs + // number of evaluations + // Markov-Chain Length (temperature is updated in every number of evaluations) + // temperature Decay + // display state ? +LAN-configuration + // the global state is updated in this number of evaluations + // 0: asynchronized mode // 1: synchronized mode + // interval of iterations to cooperate (if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/SA.hh new file mode 100644 index 0000000..9c7901a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/SA.hh @@ -0,0 +1,478 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + private: + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/SA.req.cc new file mode 100644 index 0000000..6532801 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/SA.req.cc @@ -0,0 +1,222 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + +// Problem --------------------------------------------------------------- + Problem::Problem () + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + Problem::~Problem() + {} + +// Solution -------------------------------------------------------------- + Solution::Solution (const Problem& pbm):_pbm(pbm) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + {} + + double Solution::fitness () const + { + return 0.0; + } + + char *Solution::to_String() const + { + return NULL; + } + + void Solution::to_Solution(char *_routes_) + {} + + unsigned int Solution::size() const + { + return 0; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + // Body of operator + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_1 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/StopCondition.cc new file mode 100644 index 0000000..79e3342 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((solver.current_trial()==setup.independent_runs()) && (solver.current_iteration()==setup.max_evaluations())); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.cpp new file mode 100644 index 0000000..64d179a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.cpp @@ -0,0 +1,286 @@ +/*********************************************************************** + * File: AdjKeys.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file AdjKeys.h. + ***********************************************************************/ + +#include "AdjKeys.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +AdjKeys::AdjKeys(int * parent1, int * parent2, int nbOfFrag):nof(nbOfFrag) +{ + offSpring = new int[nof]; + share = new bool[nof]; + remaining = new int[nof]; + + aKeys = new int *[nof]; + for(int i = 0; i < nof; i++) + { + aKeys[i] = new int[4]; // [0] and [1] for parent1; [2] and [3] for parent2 + for(int j = 0; j < 4; j++) + aKeys[i][j] = -1; // initialize to -1 + } + + for(int k = 0; k < nof; k++) + { + offSpring[k] = -1; + share[k] = false; + remaining[k] = 0; + } + startKey = parent1[0]; // start key point to the first fragment of parent1 + makeAdjKeysTable(parent1, parent2); +} + +/************************* + * Purpose: release memory + *************************/ + +AdjKeys::~AdjKeys() +{ + for(int i = 0; i < nof; i++) + delete [] aKeys[i]; + + delete [] aKeys; + delete [] remaining; + delete [] share; + delete [] offSpring; +} + +/**************************************************** + * Purpose: create an adjacency table for two parents + ****************************************************/ + +void AdjKeys::makeAdjKeysTable(int * parent1, int * parent2) +{ + initAdjacentcy(parent1, 1); + initAdjacentcy(parent2, 2); + + setSharing(); +// printInfo(); +} + +/******************************************* + * Purpose: initialize a parent's adjacency + *******************************************/ + +void AdjKeys::initAdjacentcy(int * parent, int pid) +{ + int indStart; + if(pid == 1) + indStart = 0; // because aKeys[][0] and aKeys[][1] for parent1 + else + indStart = 2; // because aKeys[][2] and aKeys[][3] for parent2 + + int m = 0; + for(int i = 0; i < nof; i++) + { + int key = parent[m]; + + if(m == 0) // deal with the first fragment + { + aKeys[key][indStart] = parent[m+1]; + incrementRemaining(key); + } + else if(m == nof-1) // deal with the last fragment + { + aKeys[key][indStart] = parent[m-1]; + incrementRemaining(key); + } + else // deal with the middle fragments + { + aKeys[key][indStart] = parent[m-1]; + incrementRemaining(key); + aKeys[key][indStart+1] = parent[m+1]; + incrementRemaining(key); + } + m++; + } +} + +/*********************************************** + * Purpose: return number of remaining fragments + ***********************************************/ + +int AdjKeys::getRemaining(int id) +{ + return remaining[id]; +} + +/************************************************** + * Purpose: decrement number of remaining fragments + **************************************************/ + +void AdjKeys::decrementRemaining(int id) +{ + remaining[id]--; +} + +/************************************************** + * Purpose: increment number of remaining fragments + **************************************************/ + +void AdjKeys::incrementRemaining(int id) +{ + remaining[id]++; +} + +/**************************************************** + * Purpose: set the share to be true if the fragments + * are ajdacent to both parents. + ****************************************************/ + +void AdjKeys::setSharing() +{ + for(int i = 0; i < nof; i++) + { + if(aKeys[i][0] == aKeys[i][2] || aKeys[i][0] == aKeys[i][3]) + { + share[i] = true; + remaining[i]--; + } + if(aKeys[i][1] != -1) + { + if(aKeys[i][1] == aKeys[i][2] || aKeys[i][1] == aKeys[i][3]) + { + share[i] = true; + remaining[i]--; + } + } + } +} + +/************************************ + * Purpose: check the sharing status + ************************************/ + +bool AdjKeys::hasSharing(int id) +{ + return share[id]; +} + +/***************************************************** + * Purpose: print the detail information in this class + *****************************************************/ + +void AdjKeys::printInfo() +{ + for(int i = 0; i < nof; i++) + { + cout << aKeys[i][0] << ", " << aKeys[i][1] << ", " + << aKeys[i][2] << ", " << aKeys[i][3] << "\t"; + + cout << "sharing = " << share[i] << ", " << " remain = " << remaining[i] << endl; + } +} + +/***************************************************************** + * Purpose: reset the adjacent key to be -1 if it is already taken + *****************************************************************/ + +void AdjKeys::deleteTakenKey(int takenKey) +{ + int p, q; + for(p = 0; p < nof; p++) + { + if(takenKey != p) + { + bool exist = false; + for(q = 0; q < 4; q++) + { + if(aKeys[p][q] != -1 && aKeys[p][q] == takenKey) + { + aKeys[p][q] = -1; + exist = true; + } + } + if(exist) + decrementRemaining(p); + } + } +} + +/*********************************************************** + * Purpose: performs the actual edge-recombination operation + ***********************************************************/ + +void AdjKeys::recombine() +{ + int currKey = startKey; + offSpring[0] = currKey; + deleteTakenKey(currKey); + + int i; + // produce offspring based on adjacent keys + + for(i = 1; i < nof; i++) + { + int flag = false; + int tempKeys[4] = {-1, -1, -1, -1}; + int w = 0; + for(int j = 0; j < 4; j++) + { + int t = aKeys[currKey][j]; + if(t != -1 && hasSharing(t)) + { + currKey = t; + flag = true; + break; + } + else + { + if(t != -1) + tempKeys[w++] = t; + continue; + } + } + if(!flag) + { + if(w != 0) + { + int tk = tempKeys[0]; + int moreAdjLeft = getRemaining(tk); + currKey = tk; + for(int v = 1; v < w; v++) + { + tk = tempKeys[v]; + int adjLeft = getRemaining(tk); + if(adjLeft > moreAdjLeft) + { + moreAdjLeft = adjLeft; + currKey = tk; + } + } + } + else + break; + } + offSpring[i] = currKey; + deleteTakenKey(currKey); + } + + if(i < nof) // handle special case + { + for(int x = 0; x < nof; x++) + { + if(getRemaining(x) != 0) + { + for(int y = 0; y < 4; y++) + { + if(aKeys[x][y] != -1) + { + offSpring[i++] = aKeys[x][y]; + deleteTakenKey(aKeys[x][y]); + } + } + } + } + } +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.h new file mode 100644 index 0000000..cf440b2 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AdjKeys.h @@ -0,0 +1,45 @@ +/********************************************************************* + * File: AdjKeys.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: AdjKeys class is a helper class for Edge-recombination + * crossover operator + *********************************************************************/ + +#ifndef ADJKEYS_H +#define ADJKEYS_H + +#include <iostream> +#include <string> + +using namespace std; + +class AdjKeys +{ +public: + int startKey; + int * offSpring; // store offspring generate by crossover operator + + AdjKeys(int * parent1, int * parent2, int nbOfFrag); + ~AdjKeys(); + void makeAdjKeysTable(int * parent1, int * parent2); + void initAdjacentcy(int * parent, int pid); + void recombine(); + void deleteTakenKey(int takenKey); + int getRemaining(int id); + void setSharing(); + bool hasSharing(int id); + void decrementRemaining(int id); + void incrementRemaining(int id); + void printInfo(); +private: + int ** aKeys; // store adjacent keys for both parents + bool * share; // store sharing info for both parents + int * remaining; // store remaining fragments + int nof; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/AlignedPair.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AlignedPair.h new file mode 100644 index 0000000..a5d0872 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/AlignedPair.h @@ -0,0 +1,39 @@ +/********************************************************************* + * File: AlignedPair.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: AlignedPair class is a helper class that wraps an + * alignment of two sequences + *********************************************************************/ + +#ifndef ALIGNEDPAIR_H +#define ALIGNEDPAIR_H + +#include <iostream> +#include <string> + +using namespace std; + +class AlignedPair +{ +public: + string s; // to store sequence s after alignment + string t; // to store sequence t after alignment + + AlignedPair() {} + AlignedPair(const string &s, const string &t) + { + this->s = s; + this->t = t; + } + + void printAlign() + { + cout << s << "\n" << t << endl << endl; + } +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Config.cfg new file mode 100644 index 0000000..8175e18 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/DNAFA-instances/pbm.txt +res/dna.sa.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.cpp new file mode 100644 index 0000000..ad8879e --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.cpp @@ -0,0 +1,286 @@ +/*********************************************************************** + * File: ConsensusBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file ConsensusBuilder.h. + ***********************************************************************/ + +#include "ConsensusBuilder.h" + +int Global_cutoff; + +/***************************************************** + * Purpose: build the initial consensuses from contigs + *****************************************************/ + +ConsensusBuilder::ConsensusBuilder(vector<string> &SACons) +{ + consensus = SACons; + scpList = new List1<SubConsensusPair>(); +} + +/************************* + * Purpose: release memory + *************************/ + +ConsensusBuilder::~ConsensusBuilder() +{ + delete scpList; +} + +/********************************************** + * Purpose: postprocess four types of consensus + **********************************************/ + +void ConsensusBuilder::buildConsensus() +{ + if(consensus.size() > 1) + { +// cout << endl << "case FF" << endl; +/**/ cerr << "case FF" << endl; + buildSubConsensus(FF); // both from forward strand +/**/ cerr << "End case FF" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case FR" << endl; +/**/ cerr << "case FR" << endl; + buildSubConsensus(FR); // first from forward, second from reverse complement +/**/ cerr << "End case FR" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case RF" << endl; +/**/ cerr << "case RF" << endl; + buildSubConsensus(RF); // first from reverse complement, second from forward +/**/ cerr << "End case RF" << endl; + if(consensus.size() > 1) + { +// cout << endl << "case RR" << endl;; +/**/ cerr << "case RR" << endl; + buildSubConsensus(RR); // both from reverse complement +/**/ cerr << "End case RR" << endl; + } + } + } + } +} + +/********************************************** + * Purpose: initialize four types of consensus + **********************************************/ + +void ConsensusBuilder::initST(int type) +{ + vector<string> rc; + for(int k = 0; k < consensus.size(); k++) + rc.push_back(Util::rcSequence(consensus[k])); + + s.clear(); + t.clear(); + switch(type) + { + case FF: + s = t = consensus; + break; + case FR: + s = consensus; + t = rc; + break; + case RF: + s = rc; + t = consensus; + break; + case RR: + s = t = rc; + break; + } +} + +/******************************************************** + * Purpose: detects the overlap for all possible pair of + * consensus and stores the overlap score in a + * sorted linked list in descending order. + ********************************************************/ + +void ConsensusBuilder::buildSubConsensus(int type) +{ +// cout << "\nCurrent consensus (" << type << ")" << endl; + //print(); + initST(type); + + for(int i = 0; i < s.size(); i++) + { + for(int j = i+1; j < s.size(); j++) // compute half of pairs only + { + SGA *sga = new SGA(s[i], t[j]); // eg. w1 and w2 +/**/ cerr << "Building Matrix " << i << " " << j << endl; + sga->buildMatrix(); + sga->findBestScore(); + int score = sga->getBestScore(); + delete sga; +/**/ cerr << "End Building Matrix " << i << " " << j << endl; + + if(score >= Global_cutoff) + { + scpList->insert(SubConsensusPair(i, j, score)); + scpList->insert(SubConsensusPair(j, i, score)); + } + } + } +// scpList->printList(); +/**/ cerr << "Updating Consensus" << endl; + updateConsensus(type); +/**/ cerr << "End Updating Consensus" << endl; +} + +/************************************************************ + * Purpose: update consensus information by aligning possible + * overlapping consensuses. + ************************************************************/ + +void ConsensusBuilder::updateConsensus(int type) +{ + vector<string> tempLayout; + vector<string> tepCon = consensus; + consensus.clear(); + + ListNode<SubConsensusPair>* tempNode = scpList->header->next; + + while(tempNode != NULL) + { + int cid1 = tempNode->data.cid1; + int cid2 = tempNode->data.cid2; + char direction = 'F'; // forward + + tempLayout.push_back(s[cid1]); + tempLayout.push_back(t[cid2]); + if(type == FR) + direction = 'R'; // reverse complement + + tepCon.at(cid1) = ""; + tepCon.at(cid2) = ""; + remove(scpList, cid1); + bool found = true; + while(found) + { + ListNode<SubConsensusPair>* nextNode = search(scpList, cid2); + if(nextNode == NULL) + found = false; + else + { + cid1 = cid2; + cid2 = nextNode->data.cid2; + + if(type == FR && direction == 'R') + { + tempLayout.push_back(s[cid2]); // s[cid2] = Util::rcSequence(t[cid2]) + direction = 'F'; + } + else if (type == FR && direction == 'F') + { + tempLayout.push_back(t[cid2]); + direction = 'R'; + } + else if (type == RF && direction == 'F') + { + tempLayout.push_back(s[cid2]); + direction = 'R'; + } + else + { + tempLayout.push_back(t[cid2]); + direction = 'F'; + } + + tepCon.at(cid2) = ""; + remove(scpList, cid1); + } + } + + if(tempLayout.size() > 1) + { + LayoutBuilder layoutBuilder(tempLayout); + layoutBuilder.findAlignments(); + // layoutBuilder.printAlignments(); + layoutBuilder.buildLayout(); +// cout << endl << "Merging =>"<< endl << endl; + layoutBuilder.printLayout(); + layoutBuilder.findConsensus(); + layoutBuilder.printConsensus(); + consensus.push_back(layoutBuilder.getConsensus()); + } + else + consensus.push_back(tempLayout.at(0)); + + tempLayout.clear(); + tempNode = scpList->header->next; + } + + for(int m = 0; m < tepCon.size(); m++) + { + if(tepCon.at(m) != "") + consensus.push_back(tepCon.at(m)); + } +} + +/************************************************************ + * Purpose: removes SubConsensusPair objects that contain the + * given id from the linked list. + ************************************************************/ + +void ConsensusBuilder::remove(List1<SubConsensusPair>* list, int cid) +{ + List1<SubConsensusPair>* temp = list; + ListNode<SubConsensusPair>* tempCurr = temp->header->next; + ListNode<SubConsensusPair>* tempPrev = temp->header; + + while(tempCurr != NULL) + { + if(tempCurr->data.cid1 == cid || tempCurr->data.cid2 == cid ) + { + ListNode<SubConsensusPair>* oldNode = tempCurr; + tempPrev->next = tempCurr->next; + tempCurr = tempCurr->next; + delete oldNode; + (temp->len)--; + } + else + { + tempPrev = tempCurr; + if(tempCurr != NULL) + tempCurr = tempCurr->next; + } + } +} + +/************************************************************ + * Purpose: find the SubConsensusPair object that contain the + * given id in the linked list. + ************************************************************/ + +ListNode<SubConsensusPair>* ConsensusBuilder::search(List1<SubConsensusPair>* list, int cid) +{ + ListNode<SubConsensusPair>* curr; + + for(curr = list->header->next; curr != NULL; curr = curr->next) + { + if(curr->data.cid1 == cid) // found + return curr; + } + return NULL; +} + +/*********************************** + * Purpose: prints current consensus + ***********************************/ + +void ConsensusBuilder::print() +{ +/* for(int j = 0; j < consensus.size(); j++) + cout << endl << "Cons #" << j << " => " << consensus.at(j); + cout << endl; +*/} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.h new file mode 100644 index 0000000..ea813d3 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ConsensusBuilder.h @@ -0,0 +1,53 @@ +/********************************************************************* + * File: ConsensusBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This ConsensusBuilder class is used to determine the + * sequence for contigs. + *********************************************************************/ + +#ifndef CONSENSUSBUILDER_H +#define CONSENSUSBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> +#include "list.h" +#include "Util.h" +#include "ContigBuilder.h" +#include "LayoutBuilder.h" +#include "scp.h" + +using namespace std; + +class ConsensusBuilder +{ +public: + // F - forward; R - reverse complement + enum TableType { FF, FR, RF, RR }; + + ConsensusBuilder(vector<string> &SACons); + ~ConsensusBuilder(); + + void initLayout(); // initialize layout + void buildConsensus(); + void updateConsensus(int type); + void remove(List1<SubConsensusPair> * list, int cid); + ListNode<SubConsensusPair> * search(List1<SubConsensusPair> * list, int cid); + vector<string> getConsensus() { return consensus; } + void print(); +private: + void buildSubConsensus(int type); + void initST(int type); + + List1<SubConsensusPair>* scpList; // a list of SubConsensusPair objects + vector<string> consensus; + vector<string> s, t; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.cpp new file mode 100644 index 0000000..dd7dc6f --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.cpp @@ -0,0 +1,238 @@ +/*********************************************************************** + * File: ContigBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file ContigBuilder.h. + ***********************************************************************/ + +#include "ContigBuilder.h" + +/****************************************************** + * Purpose: initialize fragment order and overlap score + ******************************************************/ + +ContigBuilder::ContigBuilder(int * order, int ** s, const SA::Problem *pbm):_pbm(pbm) +{ + fragOrder = order; + score = s; +} + +/******************************************************* + * Purpose: construct contigs based on the overlap score + * of adjacent fragments + *******************************************************/ + +void ContigBuilder::buildContigs() +{ + vector<int> tempOrder; + + int id1 = fragOrder[0]; + tempOrder.push_back(id1+1); // +1 because 0 has no negative number + int direction = 1; + + for(int i = 1; i < _pbm->numOfFragments; i++) + { + int id2 = fragOrder[i]; + // cout << "score[" << id1 << "][" << id2 << "] = " << score[id1][id2] << endl; + + int sign = direction * score[id1][id2]; + + if(abs(score[id1][id2]) >= _pbm->cutoff) // default cutoff = 30bps + { + if(sign > 0) // from same strand + { + tempOrder.push_back(id2+1); + direction = 1; + } + else // from different strand + { + tempOrder.push_back(-(id2+1)); + direction = -1; + } + id1 = id2; + } + else + { + allContigs.push_back(tempOrder); // a new contig is formed + tempOrder.clear(); + id1 = id2; + tempOrder.push_back(id1+1); + direction = 1; + } + } + allContigs.push_back(tempOrder); +} + +/******************************************************* + * Purpose: merge two contigs and update the orientation + * accordingly + *******************************************************/ + +void ContigBuilder::mergeTwoContig(int cid1, int cid2) +{ + vector<int> fids1 = allContigs.at(cid1); + vector<int> fids2 = allContigs.at(cid2); + + int fid1 = fids1.at(fids1.size()-1); + int fid2 = fids2.at(0); + int sign = fid1 * fid2; + + bool type = score[abs(fid1)-1][abs(fid2)-1] > 0; + + bool flag = (!type && sign < 0) || (type && sign > 0); // flag = true => not change + + for(int i = 0; i < fids2.size(); i++) + { + if(flag) // don't change + allContigs.at(cid1).push_back(fids2.at(i)); + else // change + allContigs.at(cid1).push_back(-fids2.at(i)); + } + + allContigs.erase(allContigs.begin() + cid2); +} + +/***************************************************** + * Purpose: merge contigs that satisfy the predefined + * threshold + *****************************************************/ + +void ContigBuilder::mergeContigs() +{ + while(allContigs.size() >= 2) + { + int bestScore = _pbm->cutoff; + int cid_i = -1; + int cid_j = -1; + + for(int i = 0; i < allContigs.size()-1; i++) + { + vector<int> tempi = allContigs.at(i); + int fidi_First = abs(tempi.at(0)) - 1; + int fidi_Last = abs(tempi.at(tempi.size()-1)) - 1; + + for(int j = i+1; j < allContigs.size(); j++) + { + vector<int> tempj = allContigs.at(j); + + int fidj_First = abs(tempj.at(0)) - 1; + int fidj_Last = abs(tempj.at(tempj.size()-1)) - 1; + + if(abs(score[fidi_Last][fidj_First]) >= bestScore) // put contig_j after contig_i + { + bestScore = abs(score[fidi_Last][fidj_First]); + cid_i = i; + cid_j = j; + } + if(abs(score[fidj_Last][fidi_First]) > bestScore) // put contig_j before contig_i + { + bestScore = abs(score[fidj_Last][fidi_First]); + cid_i = j; + cid_j = i; + } + } + } + + if(cid_i != -1 && cid_j != -1) + mergeTwoContig(cid_i, cid_j); + else + break; + } + cerr << endl << "*** *** *** *** SA Contigs ( " << allContigs.size() << " ) *** *** *** ***" << endl << endl; +} + +/******************************************* + * Purpose: build consensus for each contigs + *******************************************/ + +void ContigBuilder::buildConsensus() +{ + vector< vector<string> > fragLayouts; + for(int i = 0; i < allContigs.size(); i++) + fragLayouts.push_back(getPreLayoutFrags(allContigs.at(i))); + + vector<string> SACons; + cerr << endl << "*** *** *** *** SA Contigs ( " << fragLayouts.size() << " ) *** *** *** ***" << endl << endl; + + for(int j = 0; j < fragLayouts.size(); j++) + { + vector<string> layout = fragLayouts.at(j); + +// cout << endl << "Fragments Layout (" << j << ") =>" << endl << endl; + + if(layout.size() > 1) + { + LayoutBuilder layoutBuilder(layout); + layoutBuilder.findAlignments(); + // layoutBuilder.printAlignments(); + layoutBuilder.buildLayout(); + layoutBuilder.printLayout(); + layoutBuilder.findConsensus(); + layoutBuilder.printConsensus(); + SACons.push_back(layoutBuilder.getConsensus()); + } + else + { + SACons.push_back(layout.at(0)); +// cout << layout.at(0) << endl; + } + } + ConsensusBuilder * cb = new ConsensusBuilder(SACons); +/**/ cerr << "Building Consensus" << endl; + cb->buildConsensus(); +/**/ cerr << "End Building Consensus" << endl; + + vector<string> finalCons = cb->getConsensus(); + cerr << endl << "*** *** *** *** Final Contigs ( " << finalCons.size() << " ) *** *** *** ***" << endl << endl; +/* for(int k = 0; k < finalCons.size(); k++) + { + cout << ">Contig #" << k << endl; + cout << finalCons.at(k) << endl; + } + cout << endl << "*****************************************************" << endl; +*/ delete cb; +} + +/******************************************************** + * Purpose: returns a vector of fragments associated with + * the fragment order + ********************************************************/ + +vector<string> ContigBuilder::getPreLayoutFrags(vector<int> order) +{ + vector<string> preLayoutFrags; + + for(int i = 0; i < order.size(); i++) + { + int fid = order.at(i); + if( fid > 0) // -1 because +1 when insert + preLayoutFrags.push_back(_pbm->fragments->at(fid-1)); + else + preLayoutFrags.push_back(_pbm->rcFragments->at(abs(fid)-1)); + } +// cout << endl; + return preLayoutFrags; +} + +/*********************************************** + * Purpose: print fragment order for each contig + ***********************************************/ + +void ContigBuilder::printOrder() +{ +/* cout << endl << "Contig size = " << allContigs.size() << endl; + + for(int i = 0; i < allContigs.size(); i++) + { + vector<int> temp = allContigs.at(i); + for(int j = 0; j < temp.size(); j++) + cout << temp.at(j) << ", "; + cout << endl; + } + cout << endl; +*/} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.h new file mode 100644 index 0000000..f169c00 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/ContigBuilder.h @@ -0,0 +1,49 @@ +/********************************************************************* + * File: ContigBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This ContigBuilder class is used to process contigs + * formed from SA. + *********************************************************************/ + +#ifndef CONTIGBUILDER_H +#define CONTIGBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> + +#include "Util.h" +#include "ConsensusBuilder.h" + +#include "SA.hh" + +using namespace std; + +class ContigBuilder +{ +public: + ContigBuilder(int * order, int ** s, const SA::Problem *pbm); // constructor + ~ContigBuilder() { } // destructor + + void buildContigs(); + void buildConsensus(); + void mergeContigs(); + void mergeTwoContig(int cid1, int cid2); + void print(); + void printOrder(); + vector<string> getPreLayoutFrags(vector<int> order); + vector< vector<int> > getAllContigs() { return allContigs; } +private: + int * fragOrder; // fragment order generated by SA + int ** score; // pointer to score in OverlapDetector class + vector< vector<int> > allContigs; // set of contigs + const SA::Problem *_pbm; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.cpp new file mode 100644 index 0000000..d3ab188 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.cpp @@ -0,0 +1,423 @@ +/*********************************************************************** + * File: LayoutBuilder.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file LayoutBuilder.h. + ***********************************************************************/ + +#include "LayoutBuilder.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +LayoutBuilder::LayoutBuilder(const vector<string> & frags) +{ + preLayoutFrags = frags; + fragmentsLayout = new string[frags.size()]; + semiAlign = new AlignedPair[frags.size()-1]; +} + +/************************* + * Purpose: release memory + *************************/ + +LayoutBuilder::~LayoutBuilder() +{ + delete [] semiAlign; + delete [] fragmentsLayout; +} + +/************************************************************ + * Purpose: count number of gaps in front of a given fragment + ************************************************************/ + +int countStartGaps(const string &str) +{ + int count = 0; + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + break; + else + count++; + } + return count; +} + +/************************************************************** + * Purpose: count number of gaps at the end of a given fragment + **************************************************************/ + +int countEndGaps(const string &str) +{ + int count = 0; + for(int i = str.length() - 1; i >= 0; i--) + { + if(str.at(i) != '-') + break; + else + count++; + } + return count; +} + +/********************************************************** + * Purpose: count number of nucleotides in a given fragment + **********************************************************/ + +int countNonGapChar(const string &str) +{ + int count = 0; + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + count++; + } + return count; +} + +/**************************************** + * Purpose: create a given number of gaps + ****************************************/ + +string addGaps(int num) +{ + string gapStr = ""; + for(int i = 0; i < num; i++) + gapStr += "-"; + + return gapStr; +} + +/********************************************************** + * Purpose: count number of middle gaps in a given fragment + **********************************************************/ + +int* findMiddleGaps(const string &str, int count) +{ + int *midGapCounts = new int[count]; + int len = str.length(); + + for(int i = 0; i < count; i++) + { + midGapCounts[i] = 0; + } + + int k = 0; + for(int j = 0; j < len; j++) + { + if(str[j+1] == '-') + { + midGapCounts[k]++; + } + else + k++; + } + + return midGapCounts; +} + +/******************************************** + * Purpose: return the first non-gap position + ********************************************/ + +int findFirstNonGapPos(const string &str) +{ + for(int i = 0; i < str.length(); i++) + { + if(str.at(i) != '-') + return i; + } + return -1; +} + +/****************************************************************** + * Purpose: compute pairwise alignments for given ordered fragments + ******************************************************************/ + +void LayoutBuilder::findAlignments() +{ + for(int k = 0; k < preLayoutFrags.size()-1; k++) + { + string s = preLayoutFrags[k]; + string t = preLayoutFrags[k+1]; + SGA sga(s, t); + sga.buildMatrix(); + sga.findBestScore(); + sga.align(); + + AlignedPair aResult(sga.align_s, sga.align_t); + semiAlign[k] = aResult; + } +} + +/************************************************************* + * Purpose: insert number of gaps in front of a given fragment + *************************************************************/ + +void LayoutBuilder::insertStartGaps(int id, int numOfGaps) +{ + string temp = fragmentsLayout[id]; + string startGaps = ""; + for(int i = 0; i < numOfGaps; i++) + startGaps += "-"; + fragmentsLayout[id] = startGaps + temp; +} + +/*********************************************************** + * Purpose: insert number of gaps in the middle of fragments + ***********************************************************/ + +void LayoutBuilder::insertMiddleGaps(const string &str1, const string &str2, int k, int prev) +{ + int nonGapCount = countNonGapChar(str1); + int *midGapCounts1 = findMiddleGaps(str1, nonGapCount-1); + int *midGapCounts2 = findMiddleGaps(str2, nonGapCount-1); + + int pos = findFirstNonGapPos(fragmentsLayout[prev]); + + for(int w = 0; w < nonGapCount-1; w++) + { + pos += 1; + if(midGapCounts1[w] != 0 || midGapCounts2[w] != 0) + { + int gapDiff = abs(midGapCounts1[w] - midGapCounts2[w]); + int move = 0; + string gaps = ""; + for(int u = 0; u < gapDiff; u++) + gaps += "-"; + + if(midGapCounts1[w] > midGapCounts2[w]) + { + fragmentsLayout[k].insert(pos, gaps); + move = midGapCounts1[w]; + } + else if (midGapCounts1[w] < midGapCounts2[w]) + { + for(int v = 0; v < k; v++) + fragmentsLayout[v].insert(pos, gaps); + move = midGapCounts2[w]; + } + pos += move; + } + } + delete [] midGapCounts1; + delete [] midGapCounts2; +} + +/*************************************************************** + * Purpose: insert number of gaps at the end of a given fragment + ***************************************************************/ + +void LayoutBuilder::insertEndGaps(int id, int numOfGaps) +{ + string temp = fragmentsLayout[id]; + string endGaps = ""; + for(int i = 0; i < numOfGaps; i++) + endGaps += "-"; + fragmentsLayout[id] = temp + endGaps; +} + +/************************************************************** + * Purpose: extract fragment excluding starting and ending gaps + **************************************************************/ + +string LayoutBuilder::extractMiddleSeq(const string &str) +{ + int startGapCount = countStartGaps(str); + int endGapCount = countEndGaps(str); + int num = str.length() - startGapCount - endGapCount; + return str.substr(startGapCount, num); +} + +/************************************ + * Purpose: check if it is ending gap + ************************************/ + +bool LayoutBuilder::isEndGap(int i, int col) +{ + string middle = extractMiddleSeq(fragmentsLayout[i]); + int firstNonGap = findFirstNonGapPos(fragmentsLayout[i]); + + if(col < firstNonGap || col > firstNonGap + middle.length() - 1) + return true; + else + return false; +} + +/************************************************ + * Purpose: progressively build a fragment layout + ************************************************/ + +void LayoutBuilder::buildLayout() +{ + int j = 0; + fragmentsLayout[j++] = semiAlign[0].s; + fragmentsLayout[j++] = semiAlign[0].t; + + for(int i = 1; i < preLayoutFrags.size()-1; i++) + { + fragmentsLayout[j] = semiAlign[i].t; + + /* handle starting gaps */ + + string s_temp = semiAlign[i].s; + + int s_startGaps = countStartGaps(fragmentsLayout[j-1]); + int stemp_startGaps = countStartGaps(s_temp); + int startGapDiff = abs(s_startGaps - stemp_startGaps); + + if(startGapDiff > 0) + { + if(stemp_startGaps > s_startGaps) + { + for(int m = 0; m < j; m++) + insertStartGaps(m, startGapDiff); + } + else + insertStartGaps(j, startGapDiff); + } + + /* handle middle gaps */ + + string s_middle = extractMiddleSeq(fragmentsLayout[j-1]); + string stemp_middle = extractMiddleSeq(s_temp); + + insertMiddleGaps(s_middle, stemp_middle, j, j-1); + + /* handle end gaps */ + + int s_endGaps = countEndGaps(fragmentsLayout[j-1]); + int stemp_endGaps = countEndGaps(s_temp); + int endGapDiff = abs(s_endGaps - stemp_endGaps); + + if(endGapDiff > 0) + { + if(stemp_endGaps > s_endGaps) + { + for(int m = 0; m < j; m++) + insertEndGaps(m, endGapDiff); + } + else + insertEndGaps(j, endGapDiff); + } + j++; + } +} + +/*********************************************** + * Purpose: find majority of a particular column + ***********************************************/ + +char LayoutBuilder::majorityVote(int col) +{ + int count[5] = { 0, 0, 0, 0, 0 }; + char nucleotide[5] = {'A', 'T', 'C', 'G', '-'}; + char majority1 = 'A'; + char majority2 = 'A'; + + for(int i = 0; i < preLayoutFrags.size(); i++) + { + if(fragmentsLayout[i].at(col) == 'A') + count[0]++; + else if(fragmentsLayout[i].at(col) == 'T') + count[1]++; + else if(fragmentsLayout[i].at(col) == 'C') + count[2]++; + else if(fragmentsLayout[i].at(col) == 'G') + count[3]++; + else if(fragmentsLayout[i].at(col) == '-') + count[4]++; + } + int max = count[0]; + for(int j = 1; j < 5; j++) + { + if(count[j] > max) + { + majority2 = majority1; + max = count[j]; + majority1 = nucleotide[j]; + } + } + bool endGap = true; + if(majority1 == '-') + { + for(int i = 0; i < preLayoutFrags.size() && endGap; i++) + { + if(fragmentsLayout[i].at(col) == '-') + { + endGap = isEndGap(i, col); + } + } + + if(endGap) + return majority2; + } + return majority1; +} + +/*************************************** + * Purpose: find majority of all columns + ***************************************/ + +void LayoutBuilder::findMajority() +{ + int length = fragmentsLayout[0].length(); + + majority = ""; + for(int i = 0; i < length; i++) + { + char c = majorityVote(i); + majority += c; + } +} + +/******************************************** + * Purpose: determine sequence for the layout + ********************************************/ + +void LayoutBuilder::findConsensus() +{ + findMajority(); + consensus = ""; + for(int i = 0; i < majority.length(); i++) + { + if(majority.at(i) != '-') + consensus += majority.at(i); + } +} + +/*************************************************** + * Purpose: print info about all pairs of alignments + ***************************************************/ + +void LayoutBuilder::printAlignments() +{ + for(int j = 0; j < preLayoutFrags.size()-1; j++) + semiAlign[j].printAlign(); +} + +/*********************** + * Purpose: print layout + ***********************/ + +void LayoutBuilder::printLayout() +{ + for(int i = 0; i < preLayoutFrags.size(); i++) + cout << fragmentsLayout[i] << endl; + cout << endl; +} + +/************************** + * Purpose: print consensus + **************************/ + +void LayoutBuilder::printConsensus() +{ + cout << consensus << endl; +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.h new file mode 100644 index 0000000..3e611f5 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/LayoutBuilder.h @@ -0,0 +1,53 @@ +/********************************************************************* + * File: LayoutBuilder.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This LayoutBuilder class builds a layout for a contig. + * The contig consists of an ordered set of contiguous + * overlapping fragments. + *********************************************************************/ + +#ifndef LAYOUTBUILDER_H +#define LAYOUTBUILDER_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <string> +#include <vector> +#include "sga.h" +#include "AlignedPair.h" + +using namespace std; + +class LayoutBuilder +{ +public: + LayoutBuilder(const vector<string> & frags); // constructor + ~LayoutBuilder(); // destructor + void findAlignments(); // compute the alignments using SGA + void buildLayout(); // progressively build layout + void insertStartGaps(int id, int numOfGaps); // insert '-' at the beginning of fragments + void insertMiddleGaps(const string &str1, const string &str2, int k, int prev); + void insertEndGaps(int id, int numOfGaps); // insert '-' at the end of fragments + string extractMiddleSeq(const string &str); + bool isEndGap(int i, int col); + void findMajority(); // find majorities of the layout + char majorityVote(int col); // find majority of a particular column + void findConsensus(); + void printLayout(); + void printConsensus(); + void printAlignments(); + string getConsensus() { return consensus; } +private: + vector<string> preLayoutFrags; // ordered fragments + AlignedPair * semiAlign; // store pairwise alignment result + string * fragmentsLayout; // store layout + string majority; + string consensus; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainLan.cc new file mode 100644 index 0000000..2b937bd --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainLan.cc @@ -0,0 +1,57 @@ +#include "SA.hh" +#include "ContigBuilder.h" +#include <iostream.h> +#include <fstream.h> + +extern int Global_cutoff; + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + Global_cutoff = pbm.cutoff; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainSeq.cc new file mode 100644 index 0000000..488096d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/MainSeq.cc @@ -0,0 +1,48 @@ +#include "SA.hh" +#include "ContigBuilder.h" +#include <iostream.h> +#include <fstream.h> + +extern int Global_cutoff; + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + +//cout << pbm; + Global_cutoff = pbm.cutoff; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/Makefile b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Makefile new file mode 100644 index 0000000..275b857 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Makefile @@ -0,0 +1,25 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainScore: SA.req.o SA.pro.o StopCondition.o MainScore.o OverlapDetector.o sga.o AdjKeys.o ContigBuilder.o ConsensusBuilder.o LayoutBuilder.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/DNAFA-instances/pbm.txt res/dna.sa.seq.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.cpp new file mode 100644 index 0000000..49b81ec --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.cpp @@ -0,0 +1,130 @@ +/*********************************************************************** + * File: OverlapDetector.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file OverlapDetector.h. + ***********************************************************************/ + +#include "OverlapDetector.h" + +/************************** + * Purpose: allocate memory + **************************/ + +OverlapDetector::OverlapDetector(int nof):nbOfFrag(nof) +{ + score = new int*[nof]; + for(int i = 0; i < nof; i++) + score[i] = new int[nof]; +} + +/************************** + * Purpose: release memory + **************************/ + +OverlapDetector::~OverlapDetector() +{ + for(int j = 0; j < nbOfFrag; j++) + delete [] score[j]; + delete [] score; +} + +/********************************************************** + * Purpose: construct a score table to store overlap length + * of all possible pair of fragments + **********************************************************/ + +void OverlapDetector::buildScoresTable(vector<string>* fragments, vector<string>* rcFragments) +{ + for(int i = 0; i < nbOfFrag; i++) + { + string rcFrags = rcFragments->at(i); + + for(int j = i+1; j < nbOfFrag; j++) + { + SGA sga1(fragments->at(i), fragments->at(j)); // eg. w1 and w2 + sga1.buildMatrix(); + sga1.findBestScore(); + int score1 = sga1.getBestScore(); + + SGA sga2(rcFrags, fragments->at(j)); // eg. rcw1 and w2 + sga2.buildMatrix(); + sga2.findBestScore(); + int score2 = sga2.getBestScore(); + + if(score2 > score1) // store the larger one + score[j][i] = score[i][j] = -score2; + else + score[j][i] = score[i][j] = score1; + } + } +} + +/*************************** + * Purpose: for testing use + ***************************/ + +void OverlapDetector::readScoreTable() +{ + string inputFile = string(getenv("HOME")) + "/Mallba/ProblemInstances/DNAFA-instances/score.txt"; + ifstream inFile(inputFile.c_str(), ios::in); + if( !inFile ) + { + cout << "\n\t\t*** The file " << inputFile + << " doesn't exist! ***" << endl << endl; + exit(1); + } + +/* char seps[] = " \t\n"; + char oneLine[2000]; + int i = 0; + inFile.getline(oneLine, 2000); + while(inFile.getline(oneLine, 2000)) + { + int j = 0; + char * token = strtok(oneLine, seps); + + while (token != NULL) + { + score[i][j] = atoi(token); + token = strtok(NULL, seps); + j++; + } + i++; + }*/ + for(int i = 0; i < nbOfFrag; i++) + for(int j= 0; j < nbOfFrag; j++) + inFile >> score[i][j]; + inFile.close(); +} + +/************************************ + * Purpose: print overlap score table + ************************************/ + +void OverlapDetector::printScoreTable() +{ +// cout << endl << "*** *** *** *** Overlap Score Table *** *** *** ***" << endl << endl; + +// cout << " "; +// for(int k = 0; k < nbOfFrag; k++) +// cout << setw(5) << setiosflags(ios::right) << "F" << k; + + for(int i = 0; i < nbOfFrag; i++) + { + cout << endl; +// cout << "F" << i << " "; + for(int j = 0; j < nbOfFrag; j++) + { + if(i == j) + cout << setw(5) << setiosflags(ios::right) << "0 "; + else + cout << setw(5) << setiosflags(ios::right) << score[i][j] << " "; + } + } +// cout << endl << endl << "*****************************************************" << endl; +} + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.h new file mode 100644 index 0000000..a0a0594 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/OverlapDetector.h @@ -0,0 +1,45 @@ +/*************************************************************** + * File: OverlapDetector.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This OverlapDetector class is used to detect the + * similarity of all possible pair of fragments. The + * overlap length between any two fragments is stored + * in a two dimentional array called score. + ***************************************************************/ + +#ifndef OVERLAPDETECTOR_H +#define OVERLAPDETECTOR_H + +#pragma warning(disable: 4786) + +#include <iostream> +#include <fstream> +#include <iomanip> +#include <stdlib.h> +#include <string> +#include <vector> + +#include "sga.h" + +using namespace std; + + +class OverlapDetector +{ +public: + OverlapDetector(int nof); // constructor + ~OverlapDetector(); // destructor + void buildScoresTable(vector<string>*, vector<string>*); // build overlap score table for fragments + void readScoreTable(); + void printScoreTable(); + int ** getScoreTable() { return score; } +private: + int ** score; // to store the overlap length of all possible pair of fragments + int nbOfFrag; // Number of Fragments +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.cfg new file mode 100644 index 0000000..739dc52 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +25600 // number of evaluations +256 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +200000 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +200 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.hh new file mode 100644 index 0000000..c8d6914 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.hh @@ -0,0 +1,494 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> +#include <vector> +#include "OverlapDetector.h" + +using namespace std; + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int numOfFragments; // number of fragments^M + double avgLength; // average length of the input fragments^M + int cutoff; // overlap threshold^M + int * fragmentLength; // fragments' lengths^M + vector<string>* fragments; // forward direction of the fragments^M + vector<string>* description; // description of the fragments (Nombre Del Fragmento)^M + vector<string>* rcFragments; // reverse complement of the fragments + OverlapDetector *detector; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness (); + int& fragment(const int index); + int* fragments(); + + private: + int * fragOrder; // an order of an individual ^M + const Problem& _pbm; + + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc new file mode 100644 index 0000000..a89284b --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc @@ -0,0 +1,1808 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + /* if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + */ + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc1 b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc1 new file mode 100644 index 0000000..3d95a77 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.pro.cc1 @@ -0,0 +1,1837 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" +#include "ContigBuilder.h" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %d ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + +/* if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1);*/ + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + +cerr << current_best_cost() << endl; + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + { + run(params.max_evaluations()); +// cerr << "Entrado" << endl; +// Solution s(current_best_solution()); +// cerr << s; +// ContigBuilder * builder = new ContigBuilder(s.fragments(), problem.detector->getScoreTable(),&problem); +// builder->buildContigs(); +// builder->mergeContigs(); +// // builder->buildConsensus(); +// delete builder; + + } + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { +cout << "ConstructorA " << endl; + NetStream::init(argc,argv); +cout << "ConstructorB " << endl; + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); +cout << "Constructor " << endl; + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + { + run(params.max_evaluations()); + if(mypid == 0) + { +// cerr << "Entrado" << endl; +// Solution s(current_solution()); +// cerr << s; +// ContigBuilder * builder = new ContigBuilder(s.fragments(), problem.detector->getScoreTable(),&problem); +// builder->buildContigs(); +// builder->mergeContigs(); +// // builder->buildConsensus(); +// delete builder; + } + } + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.req.cc new file mode 100644 index 0000000..153f37c --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/SA.req.cc @@ -0,0 +1,437 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" +#include <math.h> +#include "Util.h" +#include "AdjKeys.h" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():numOfFragments(0),avgLength(0.0),cutoff(0), + fragmentLength(NULL),fragments(NULL),rcFragments(NULL), + description(NULL) + { + } + + ostream& operator<< (ostream& os, const Problem& pbm) + { + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm.cutoff); + + is.getline(buffer,MAX_BUFFER,'\n'); +//cout << buffer; + ifstream f((string(getenv("HOME")) + buffer).c_str()); + + int seqCount = -1; + pbm.fragments = new vector<string>(); + pbm.description = new vector<string>(); + + /* read fragments from input file and store its description in descr[] + and its sequence in sequence[] */ + + char oneLine[2000]; + string sequence; + string upperSeq; + while(f.getline(oneLine, 2000)) + { +//cout << oneLine; + string temp = string(oneLine); + int rightArrow = temp.find_first_of(">"); + if(rightArrow != -1) //rightArrow is found + { + seqCount++; + if(seqCount != 0) + pbm.fragments->push_back(sequence); + int space = temp.find(" ", rightArrow); + pbm.description->push_back(temp.substr(rightArrow+1, space)); + sequence = ""; + } + else //line doesn't start with rightArrow + { + upperSeq = ""; + for(int i = 0; i < temp.length(); i++) + upperSeq += toupper(temp.at(i)); + + sequence.append(upperSeq); + } + } + pbm.fragments->push_back(sequence); + f.close(); + + pbm.numOfFragments = pbm.fragments->size(); + pbm.fragmentLength = new int[pbm.numOfFragments]; + + pbm.rcFragments = new vector<string>(); + + for(int j = 0; j < pbm.numOfFragments; j++) + { + pbm.rcFragments->push_back(Util::rcSequence(pbm.fragments->at(j))); +//cout << pbm.description->at(j) << " " << pbm.fragments->at(j) << " " << pbm.rcFragments->at(j) << endl; + } + + int sumLength = 0; + for(int i = 0; i < pbm.numOfFragments; i++) + { + pbm.fragmentLength[i] = pbm.fragments->at(i).length(); + sumLength += pbm.fragmentLength[i]; + } + pbm.avgLength = (double)sumLength / (double)pbm.numOfFragments; + + pbm.detector = new OverlapDetector(pbm.numOfFragments); +// pbm.detector->buildScoresTable(pbm.fragments, pbm.rcFragments); + pbm.detector->readScoreTable(); +// pbm.detector->printScoreTable(); + + return is; + } + + bool Problem::operator== (const Problem& pbm) const + { + // Falta terminar + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; // F1 +// return minimize; // F2 + } + + Problem::~Problem() + { + delete detector; + delete fragments; + delete rcFragments; + delete description; + delete [] fragmentLength; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),fragOrder(new int[pbm.numOfFragments]) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + if(fragOrder != NULL) delete [] fragOrder; + + fragOrder = new int [_pbm.numOfFragments]; + + for(int i = 0; i < _pbm.numOfFragments; i++) + fragOrder[i] = sol.fragOrder[i]; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + is >> sol.fragOrder[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + os << " " << sol.fragOrder[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + ns << sol.fragOrder[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol.pbm().numOfFragments;i++) + ns >> sol.fragOrder[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + if(fragOrder != NULL) delete [] fragOrder; + + fragOrder = new int [_pbm.numOfFragments]; + + for(int i = 0; i < _pbm.numOfFragments; i++) + fragOrder[i] = sol.fragOrder[i]; + + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + for(int i = 0; i < _pbm.numOfFragments; i++) + if(fragOrder[i] != sol.fragOrder[i]) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + int * randNum = new int[_pbm.numOfFragments]; + + for(int k = 0; k < _pbm.numOfFragments; k++) + { + int num = rand_int(0, _pbm.numOfFragments * 2); + randNum[k] = num; + fragOrder[k] = k; + } + + // sort value and store index as fragment order + for(int i = 0; i < _pbm.numOfFragments-1; i++) + { + for(int j = i+1; j < _pbm.numOfFragments; j++) + { + if( randNum[i] > randNum[j]) + { + int temp = randNum[i]; + randNum[i] = randNum[j]; + randNum[j] = temp; + + temp = fragOrder[i]; + fragOrder[i] = fragOrder[j]; + fragOrder[j] = temp; + } + } + } + delete [] randNum; + } + + double Solution::fitness () + { + int ** score = _pbm.detector->getScoreTable(); + // F1 maximization + int fit = 0; + + for(int k = 0; k < _pbm.numOfFragments-1; k++) + { + int i = fragOrder[k]; + int j = fragOrder[k+1]; + + fit += abs(score[i][j]); + } + return (double) fit; + // F2 minimization +/* int fit = 0; + int nof = _pbm.numOfFragments; + + for(int i = 0; i < nof; i++) + { + int m = fragOrder[i]; + for(int j = 0; j < nof; j++) + { + if(i != j) + { + int n = fragOrder[j]; + if((nof<m) || (nof<n) || (m<0) || (n<0)) + { + cout << "Error en indices" << endl; + return infinity(); + } + fit += abs(i-j) * abs(score[m][n]); + } + } + } + return (double)fit; +*/ } + + char *Solution::to_String() const + { + return (char *)fragOrder; + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + + for (int i=0;i<_pbm.numOfFragments;i++) + { + fragOrder[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.numOfFragments * sizeof(int)); + } + + + int& Solution::fragment(const int index) + { + return fragOrder[index]; + } + + + int* Solution::fragments() + { + return fragOrder; + } + + Solution::~Solution() + { + delete [] fragOrder; + } + + // UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + int indsize = sol.pbm().numOfFragments; + int r1 = rand_int(0, indsize-1); + int r2 = rand_int(0, indsize-1); + + while(r2 == r1) + { + if(r1 == indsize-1) r2 = rand_int(0, indsize-2); + else r2 = rand_int(r1, indsize-1); + } + + /* // swap + int temp = sol.fragment(r1); + sol.fragment(r1) = sol.fragment(r2); + sol.fragment(r2) = temp; +*/ + // 2-opt + if(r2 < r1) + { + int temp = r1; + r1 = r2; + r2 = temp; + } + while(r2 > r1) + { + int temp = sol.fragment(r1); + sol.fragment(r1) = sol.fragment(r2); + sol.fragment(r2) = temp; + ++r1; + --r2; + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.cc new file mode 100644 index 0000000..2033972 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (false); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/Util.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Util.h new file mode 100644 index 0000000..fcea0d2 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/Util.h @@ -0,0 +1,71 @@ +/************************************************************** + * File: Util.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This Util class consists of utility functions + * used by other classes + **************************************************************/ + +#ifndef UTIL_H +#define UTIL_H + +#include <stdlib.h> +#include <vector> + +using namespace std; + +class Util +{ +public: + /* returns a randomly generated floating point number ranged [min, max] */ +// static double randDouble(double min, double max) +// { +// return (1.0*rand()*(max-min)/RAND_MAX + min); +// } + + /* returns a randomly generated interge number ranged [min, max] */ +// static int randInt(int min, int max) +// { +// return (int)randDouble(min, max); +// } + + /* returns a string that is the reverse of a given DNA sequence */ + static string revSequence(const string &s) + { + string revSeq = s; + int j = 0; + for(int i = s.length()-1; i >= 0; i--) + revSeq[j++] = s.at(i); + + return revSeq; + } + + /* returns a string that is the complement of a given DNA sequence */ + static string complSequence(const string &s) + { + string compSeq = s; + int j = 0; + for(unsigned int i = 0; i < s.length(); i++) + { + if(s.at(i) == 'A') + compSeq[j++] = 'T'; + else if(s.at(i) == 'T') + compSeq[j++] = 'A'; + else if(s.at(i) == 'C') + compSeq[j++] = 'G'; + else if(s.at(i) == 'G') + compSeq[j++] = 'C'; + else + compSeq[j++] = s.at(i); + } + return compSeq; + } + + /* returns a string that is the reverse complement of a given DNA sequence */ + static string rcSequence(const string &s) + { + return complSequence(revSequence(s)); + } +}; +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/list.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/list.h new file mode 100644 index 0000000..46eff2e --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/list.h @@ -0,0 +1,300 @@ +/*************************************************************** + * File: list.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This List class is a template class. It builds a + * single linked list of any type of objects. + ***************************************************************/ + +#ifndef LIST_H +#define LIST_H + +#include <assert.h> +#include <stdlib.h> +#include <iostream> +using namespace std; + +template <class T> +struct ListNode +{ + T data; // T could be any type of object + ListNode<T> *next; +}; + +template <class T> +class List1 +{ +public: + ListNode<T>* header; // header is a dummy node + ListNode<T>* current; + int len; // length of the linked list + + List1(); // constructor + ~List1(); // destructor + + List1(const List1<T> & source); // copy constructor + List1<T> & operator=(const List1<T> & source); + void append(const T); // append data at the end of list + void insert(const T); // insert data in order + void insertPtr(const T); // insert pointer type of object in order + void insertFront(const T); // insert data at the beginning of the list + void remove(const T); // delete data from list + void next(); + void prev(); + void reset(); + void clear(); + int length() const { return len; } + bool isEmpty() const; // check whether list is empty + bool isFull() const; // check whether memory is allocated + T value() const; // return content of the data + void printList(); + void printListPtr(); + ListNode<T>* findPrevious(const T); + ListNode<T>* search(const T); +}; + +template <class T> +List1<T>::List1() +{ + header = new ListNode<T>; + header->next = NULL; + current = header; + len = 0; +} + +template <class T> +List1<T>::List1(const List1<T> & source) +{ + header = NULL; + *this = source; +} + +template <class T> +List1<T> & List1<T>::operator=(const List1<T> & source) +{ + if(this != &source) + { + ListNode<T> * current = source.header; + while(current != NULL) + { + insert(current->data); + current = current->pnext; + } + } + return *this; +} + +template <class T> +void List1<T>::clear() +{ + ListNode<T> *tmp; + ListNode<T> *previous = header; + ListNode<T> *traverse = header->next; + + while(traverse != NULL) // release memory from list + { + tmp = traverse; + previous->next = traverse->next; + traverse = traverse->next; + delete tmp; + } + current = header; + len = 0; +} + +template <class T> +List1<T>::~List1() +{ + clear(); + delete header; +} + + +template <class T> +void List1<T>::insert(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + if(len == 0) // no need to traverse + { + newNode->next = current->next; + current->next = newNode; + } + else // need to traverse + { + ListNode<T> * temp = header; + while((temp->next != NULL) && (item < temp->next->data)) + temp = temp->next; + newNode->next = temp->next; + temp->next = newNode; + } + len++; +} + +template <class T> +void List1<T>::insertPtr(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + if(len == 0) // no need to traverse + { + newNode->next = current->next; + current->next = newNode; + } + else // need to traverse + { + ListNode<T> * temp = header; + while((temp->next != NULL) && (*item < *(temp->next->data))) // pointer need dereference + temp = temp->next; + newNode->next = temp->next; + temp->next = newNode; + } + len++; +} + +template <class T> +void List1<T>::insertFront(const T item) +{ + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = header->next; + header->next = newNode; + len++; +} + +template <class T> +void List1<T>::append(const T item) +{ + assert(!isFull()); + ListNode<T> * newNode = new ListNode<T>; + newNode->data = item; + newNode->next = NULL; + ListNode<T> *traverse = header; + while(traverse->next != NULL) + traverse = traverse->next; + traverse->next = newNode; + len++; +} + +template <class T> +ListNode<T>* List1<T>::findPrevious(const T target) +{ + ListNode<T> *temp; + + for(temp = header; temp->next != NULL; temp = temp->next) + if(*(temp->next->data) == *target) + return temp; + + return NULL; +} + +template <class T> +void List1<T>::remove(const T target) +{ + if(len != 0) + { + ListNode<T> *p = findPrevious(target); + if(p->next != NULL) + { + ListNode<T> *oldNode = p->next; + p->next = p->next->next; + delete oldNode; + len--; + } + } +} + +template <class T> +void List1<T>::next() +{ + current = current->next; +} + +template <class T> +void List1<T>::prev() +{ + if(len > 1) + { + ListNode<T>* tmp = header; + while(tmp->next != current) + tmp = tmp->nect; + + current = tmp; + } +} + +template <class T> +void List1<T>::reset() +{ + current = header; +} + +template <class T> +bool List1<T>::isEmpty() const +{ + return (len == 0); +} + +template <class T> +bool List1<T>::isFull() const +{ + ListNode<T> *tmp = new ListNode<T>; + if(tmp == NULL) + return true; + else + { + delete tmp; + return false; + } +} + +template <class T> +T List1<T>::value() const +{ + return current->next->data; +} + +template <class T> +ListNode<T>* List1<T>::search(const T target) +{ + ListNode<T> *temp; + + for(temp = header->next; temp != NULL; temp = temp->next) + if((*target) == *(temp->data)) + return temp; + + return NULL; +} + +template <class T> +void List1<T>::printList() +{ + cout << endl; + for(int i = 0; i < len; i++) + { + cout << value(); + next(); + } + reset(); +} + +template <class T> +void List1<T>::printListPtr() +{ + cout << endl; + for(int i = 0; i < len; i++) + { + cout << *(value()); // pointer need dereference + next(); + } + reset(); +} + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/dnafa/pgfileLan new file mode 100644 index 0000000..d8a0011 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/pgfileLan @@ -0,0 +1,3 @@ +localhost 0 ~/Mallba/rep/SA/dnafa/MainLan +localhost 1 ~/Mallba/rep/SA/dnafa/MainLan +localhost 1 ~/Mallba/rep/SA/dnafa/MainLan diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/scp.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/scp.h new file mode 100644 index 0000000..86960d6 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/scp.h @@ -0,0 +1,53 @@ +/******************************************************************* + * File: scp.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This SubConsensusPair class is used to create + * SubConsensusPair objects for ConsensusBuilder class + *******************************************************************/ + +#ifndef SCP_H +#define SCP_H + +#include <iostream> + +using namespace std; + +class SubConsensusPair +{ +public: + int cid1; // first consensus's ID + int cid2; // second consensus's ID + int score; // overlap score between two consensuses + + SubConsensusPair() { } // default constructor + SubConsensusPair(int id1, int id2, int s) // user defined constructor + { + cid1 = id1; + cid2 = id2; + score = s; + } + virtual ~SubConsensusPair() { } // destructor + + bool operator<(const SubConsensusPair& source) const + { + if(score < source.score) + return true; + else + return false; + } + /* overload operator<< for printing the contents of a SubConsensusPair object */ + friend ostream& operator<<(ostream& os, const SubConsensusPair &info) + { + os << "(" << info.cid1 << ", " << info.cid2 << ", " << info.score << ")" << endl; + return os; + } +}; + + /* overload operator<< for printing the contents of a SubConsensusPair object */ + //ostream& operator<<(ostream& os, const SubConsensusPair& info) + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.cpp b/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.cpp new file mode 100644 index 0000000..29d740b --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.cpp @@ -0,0 +1,256 @@ +/*********************************************************************** + * File: sga.cpp + * Author: Lishan Li + * Date: May, 2003 + * + * Description: It provides implementation of all the functions declared + * in the header file sga.h. + ***********************************************************************/ + +#include "sga.h" + +/********************************************* + * Purpose: allocate memory and initialization + *********************************************/ + +SGA::SGA(const string &is, const string &it) +{ + g = -2; // gap penalty = -2 + s = is; + t = it; + m = s.length(); + n = t.length(); +// /**/ cout << "\t size " << m+1 << " x " << n+1 << endl; + bestScore = 0; +} + +/************************* + * Purpose: release memory + *************************/ + +SGA::~SGA() +{ +} + + +/******************************************************* + * Purpose: Build a score matrix to store the scores of + * pairwise semiglobal alignment + *******************************************************/ + +void SGA::CalculateBest(int i, int j, int score) +{ +//cout << "(" << i<<","<< j<<","<<score<<")"<<endl; + if(j == n) + { + if((score == n) && (score > bestScore)) // ------- + { // --- + bestScore = score; + overlapType = 1; + } + else if((score == i) && (score > bestScore)) // ------- + { // ------- + bestScore = score; + overlapType = 2; + } + } + + if(i == m) + { + if((score == m) && (score > bestScore)) // --- + { // --------- + bestScore = score; + overlapType = 3; + } + else if((score == j) && (score > bestScore)) // ------- + { // ------- + bestScore = score; + overlapType = 4; + } + } +} + +void SGA::buildMatrix() +{ + // Primero la mitad superior + int i,j,k; + int score; + bestScore = 0; + overlapType = 3; + for(k = 1; k <= m; k++) + { + score = 0; + i = k; + j = 1; + while((j <=n) && (i <=m)) + { + if(p(i,j) == 1) + score = score + 1; + else + score = 0; + j++; + i++; + } + i--;j--; + CalculateBest(i,j,score); + } + + for(k = 2; k <= n; k++) + { + score = 0; + j = k; + i = 1; + while(j <=n && i <=m) + { + if(p(i,j) == 1) + score = score + 1; + else + score = 0; + j++; + i++; + } + i--;j--; + CalculateBest(i,j,score); + } +} + +/*************************** + * match score = 1 + * mismatch score = -1 + ***************************/ + +int SGA::p(int i, int j) +{ + if (s[i-1] == t[j-1]) // match + return 1; + else + return -1; +} + +/**************************************************** + * Purpose: find the maximum number of x, y, and z + ****************************************************/ + +int SGA::max(int x, int y, int z) +{ + int temp = x; + if (x < y) + temp = y; + if (temp < z) + temp = z; + return temp; +} + +/******************************************************************** + * Purpose: find the best score for the pairwise semiglobal alignment + ********************************************************************/ + +void SGA::findBestScore() +{ +} + + +/********************************************************************** + * Purpose: Align the two sequence starting from the the row and column + * with the best score + **********************************************************************/ + +void SGA::align() +{ + int i; + int start; +//cout << s << endl << t << endl << bestScore << " " << overlapType << endl; +//exit(-1); + string preGaps = ""; + string postGaps = ""; + if((start = s.find(t)) != string::npos) // t is substring of s + { + align_s = s; + for(i = 0; i < start; i++) + preGaps += "-"; + align_t = preGaps + t; + + for(i = start+bestScore; i < m; i++) + postGaps += "-"; + align_t += postGaps; + } + else if((start = t.find(s)) != string::npos) // s is substring of t + { + align_t = t; + for(i = 0; i < start; i++) + preGaps += "-"; + align_s = preGaps + s; + + for(i = start+bestScore; i < n; i++) + postGaps += "-"; + align_s += postGaps; + } + else if(overlapType == 4) + { + int preNumGaps = m - bestScore; + for(int i = 0; i < preNumGaps; i++) + preGaps += "-"; + align_t = preGaps + t; + + int postNumGaps = align_t.length() - m; + for(int j = 0; j < postNumGaps; j++) + postGaps += "-"; + align_s = s + postGaps; + } + else + { + int preNumGaps = n - bestScore; + for(int i = 0; i < preNumGaps; i++) + preGaps += "-"; + align_s = preGaps + s; + + int postNumGaps = align_s.length() - n; + for(int j = 0; j < postNumGaps; j++) + postGaps += "-"; + align_t = t + postGaps; + } +} + +/************************************************************ + * Purpose: Print the score matrix for the pairwise alignment + ************************************************************/ + +void SGA::printMatrix() +{ +/* for (int i = 0; i <= m; i++) + { + cout << endl; + for (int j = 0; j <= n; j++) + { + printf("%3d", score[i][j]); + } + } + cout << endl << endl; + cout << "The best score is: " << bestScore << endl << endl;*/ +} + +/*************************************** + * Purpose: Print the pairwise alignment + ***************************************/ + +void SGA::printAlign() +{ + cout << align_s << endl; + cout << align_t << endl << endl; +} + +/******************************* + * Purpose: Print Info for debug + *******************************/ +void SGA::printInfo() +{ + cout << "m = " << m << " n = " << n << " g = " << g + << " bestRow = " << bestRow << " bestCol = " << bestCol << " bestscore = " << bestScore + << endl; + cout << "s = " << align_s << " t = " << align_t << endl; + +// printMatrix(); +} + +/************************************ End of File **************************************/ + diff --git a/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.h b/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.h new file mode 100644 index 0000000..1cf336d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/dnafa/sga.h @@ -0,0 +1,52 @@ +/*************************************************************** + * File: sga.h + * Author: Lishan Li + * Date: May, 2003 + * + * Description: This SGA class is used to do pairwise alignment + * between two fragments + ***************************************************************/ + +#ifndef SGA_H +#define SGA_H + +#include <iostream> +#include <string> +using namespace std; + +class SGA +{ +public: + string align_s; // to store sequence s after alignment + string align_t; // to store sequence t after alignment + + SGA() {} // default constructor + SGA(const string &is, const string &it); // user defined constructor + ~SGA(); // destructor + void buildMatrix(); + int p(int i, int j); + void align(); + void findBestScore(); + void printMatrix(); + void printAlign(); + void printInfo(); + int getBestRow() { return bestRow; } + int getBestCol() { return bestCol; } + int getBestScore() { return bestScore; } +private: + int max(int x, int y, int z); + void CalculateBest(int i, int j, int score); + string s, t; + int g; // gap + int m; // length of s + int n; // length of t + int bestRow; // the row containning best score + int bestCol; // the column containing best score + int bestScore; // the best score of the semiglobal alignment +// int ** score; // to store the scores for pairwise alignment + int overlapType; +}; + +#endif + +/************************************ End of File **************************************/ diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/maxsat/Config.cfg new file mode 100644 index 0000000..2d6daf7 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/MAXSAT-instances/sat1.txt +res/sat1.sa.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/Makefile b/ProyectoFinal/CHC/malva/rep/SA/maxsat/Makefile new file mode 100644 index 0000000..0ffc8d9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/MAXSAT-instances/sat1.txt res/sat1.sa.seq.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.cfg new file mode 100644 index 0000000..0aef72f --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +500 // number of evaluations +10 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.hh new file mode 100644 index 0000000..26c7864 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.hh @@ -0,0 +1,493 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem(); + ~Problem(); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + double infinity() const; + + int numvar() const; + int numclause() const; + int lenclause() const; + int *clause(const int i) const; + + + private: + + int _numvar; + int _numclause; + int _lenclause; + int ** _clauses; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_cadena_); + + void initialize(); + double fitness (); + unsigned int size() const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.pro.cc b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.req.cc new file mode 100644 index 0000000..f3554e7 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/SA.req.cc @@ -0,0 +1,364 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_numvar(0),_numclause(0),_clauses(NULL),_lenclause(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of variables " << pbm._numvar + << endl << endl << "Number of clauses " << pbm._numclause + << endl << endl << "Length of clauses " << pbm._lenclause + << endl << endl + << " Clauses: " << endl; + + for (int i=0;i<pbm._numclause;i++) + { + os << "\t clause " << i << "\t "; + for(int j = 0; j < pbm._lenclause; j++) + os << pbm._clauses[i][j] << " "; + os << endl; + } + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + int l; + int n; + is >> pbm._numvar >> pbm._numclause >> pbm._lenclause; + + n = pbm._lenclause; + // read clauses + pbm._clauses = new int*[pbm._numclause]; + + for (int i = 0; i < pbm._numclause; i++) + { + pbm._clauses[i] = new int[n]; + for(int j = 0; j < n;j++) + { + is >> l; + pbm._clauses[i][j] = l; + } + is >> l; + } + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + int n; + _numvar=pbm.numvar(); + for(int i = 0; i < _numclause;i++) + delete [] _clauses[i]; + delete [] _clauses; + + _numclause = pbm.numclause(); + n = _lenclause = pbm.lenclause(); + + _clauses = new int *[_numclause]; + + for(int i = 0; i < pbm._numclause;i++) + { + _clauses[i] = new int [n]; + for(int j = 0; j < n ; j++) + _clauses[i][j] = pbm._clauses[i][j]; + } + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_numvar!=pbm.numvar()) return false; + for (int i = 0; i < _numclause; i++) + for(int j = 0; j < _lenclause;j++) + if ( _clauses[i][j] != pbm._clauses[i][j]) + return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + double Problem::infinity() const + { + double one=1.0; + double zero=0.0; + return 0.0 - one/zero; + } + + int Problem::numvar() const + { + return _numvar; + } + + int Problem::numclause() const + { + return _numclause; + } + + int Problem::lenclause() const + { + return _lenclause; + } + + int *Problem::clause(const int i) const + { + return _clauses[i]; + } + + Problem::~Problem() + { + for(int i = 0;i < _numclause;i++) + delete [] _clauses[i]; + + delete [] _clauses; + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.numvar()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().numvar();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().numvar();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var = sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.numvar();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () + { + double fitness = 0.0; + int acum = 0; + + for(int i = 0; i < _pbm.numclause(); i++) + { + int *rl = _pbm.clause(i); + acum = 0; + for(int j = 0; (j < _pbm.lenclause()) && (acum != 1);j++) + { + if( ((rl[j] < 0) && (_var[(int)abs(rl[j])-1] == 0)) + || ((rl[j] > 0) && (_var[rl[j]-1] == 1)) ) + acum = 1; + } + fitness += acum; + } + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.numvar();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.numvar() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().numvar();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.cc new file mode 100644 index 0000000..dcd0513 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.numclause()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/maxsat/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/maxsat/pgfileLan new file mode 100644 index 0000000..a681b21 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/maxsat/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan +localhost 1 ~/Mallba/rep/SA/maxsat/MainLan diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/onemax/Config.cfg new file mode 100644 index 0000000..87d424d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.sa.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/onemax/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/onemax/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/Makefile b/ProyectoFinal/CHC/malva/rep/SA/onemax/Makefile new file mode 100644 index 0000000..82415bb --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/ONEMAX-instances/onemax10.txt res/om10.sa.seq.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.cfg new file mode 100644 index 0000000..b6c9399 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +500 // number of evaluations +5 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.hh @@ -0,0 +1,488 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int dimension() const; + double infinity() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.pro.cc b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.req.cc new file mode 100644 index 0000000..a327cb3 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/SA.req.cc @@ -0,0 +1,286 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + double Problem::infinity() const + { + double one=1.0; + double zero=0.0; + return 0.0 - one/zero; + } + + Problem::~Problem() + { + } + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () const + { + double fitness = 0.0; + + for (int i=0;i<_var.size();i++) + fitness += _var[i]; + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.dimension()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/onemax/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/onemax/pgfileLan new file mode 100644 index 0000000..fa76afb --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/onemax/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan +localhost 1 ~/Mallba/rep/SA/onemax/MainLan diff --git a/ProyectoFinal/CHC/malva/rep/SA/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/pgfileLan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/pgfileLan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/ProyectoFinal/CHC/malva/rep/SA/pgfileWan b/ProyectoFinal/CHC/malva/rep/SA/pgfileWan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/pgfileWan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/rnd/Config.cfg new file mode 100644 index 0000000..c8bac1a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/RND-instances/rnd149.txt +res/rnd149.sa.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/rnd/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/rnd/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/Makefile b/ProyectoFinal/CHC/malva/rep/SA/rnd/Makefile new file mode 100644 index 0000000..b15a6cd --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/RND-instances/rnd149.txt res/rnd149.sa.seq.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.cfg new file mode 100644 index 0000000..1dbac85 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +5000 // number of evaluations +50 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +10 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.hh @@ -0,0 +1,488 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int dimension() const; + double infinity() const; + + private: + + int _dimension; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int& var(const int index); + Rarray<int>& array_var(); + + private: + Rarray<int> _var; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.pro.cc b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.req.cc new file mode 100644 index 0000000..1702a43 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/SA.req.cc @@ -0,0 +1,385 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** Tab size = 4 *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +//Parámetros para RND ------------------------------------------------------------- + +#define GRID_SIZE_X 287 //Artificial grid horizontal size. +#define GRID_SIZE_Y 287 //Artificial grid vertical size. +#define GRID_SIZE 82369 //Total grid size. +#define TRANS_NUMB 59 //Number of transmiters used. +#define TRANS_TOTAL 349 //Number of total transmiters. + //49 transmiters distributed regulary... + //... the rest is distributed randomly. + +#define RANGE 20 //Transmiter cover range (square area) + +//------------------------------------------------------------------------------------------------------- +#define TARGET_FITNESS 204.08 //Fitness to be achieved in current trial +//------------------------------------------------------------------------------------------------------- + + +#define MAX_FIT 204.08 //Fitness for optimum solution. +#define AVG_B -4.878 //Coef. for linear penalty of fitness value ... +#define AVG_A 4.878 // ... depending on avg. and dev. overlapping. +#define DEV_B 0.0 +#define DEV_A 2.404 + +//--------------------------------------------------------------------------------- + +skeleton SA { + + + + + //Array ------------------------------------------------------------------ + + static short int trans_location[TRANS_TOTAL*2]= + {20,20, 61,20, 102,20, 143,20, 184,20, 225,20, 266,20, + 20,61, 61,61, 102,61, 143,61, 184,61, 225,61, 266,61, + 20,102, 61,102, 102,102, 143,102, 184,102, 225,102, 266,102, + 20,143, 61,143, 102,143, 143,143, 184,143, 225,143, 266,143, + 20,184, 61,184, 102,184, 143,184, 184,184, 225,184, 266,184, + 20,225, 61,225, 102,225, 143,225, 184,225, 225,225, 266,225, + 20,266, 61,266, 102,266, 143,266, 184,266, 225,266, 266,266, + + 169,180, 180,161, 160,233, 57,156, 158,145, 138,151, 160,32, + 165,36, 228,111, 251,181, 110,130, 286,19, 96,183, 91,133, + 88,74, 93,56, 35,273, 152,198, 142,181, 37,117, 271,193, + 49,109, 104,119, 110,54, 58,160, 135,204, 220,172, 4,141, + 160,244, 210,14, 36,37, 98,3, 134,226, 197,109, 101,17, + 112,230, 169,126, 215,44, 206,27, 18,90, 14,272, 40,134, + 160,150, 58,216, 170,37, 252,185, 246,142, 154,247, 180,128, + 188,55, 207,201, 134,15, 31,111, 166,34, 206,116, 223,261, + 94,48, 227,179, 24,250, 46,26, 159,245, 279,56, 235,43, + 195,166, 165,241, 203,9, 190,73, 20,91, 25,200, 211,255, + 260,199, 262,66, 283,120, 16,76, 38,112, 201,172, 144,1, + 273,282, 230,285, 222,240, 70,132, 240,40, 202,147, 35,175, + 24,41, 4,120, 88,114, 23,104, 274,142, 83,230, 281,265, + 248,58, 140,42, 136,185, 17,2, 9,42, 156,115, 216,32, + 242,104, 221,224, +241,113,224,229,261,56,96,220,79,158,137,180,104,147,273,262,182,205,40,174, +4,69,39,230,44,115,37,31,286,62,147,240,175,84,182,150,141,279,83,221, +151,220,114,255,81,101,231,263,20,272,150,24,55,190,255,100,18,5,131,18, +68,278,258,244,76,154,107,218,147,191,152,11,125,267,267,206,81,211,183,101, +197,47,126,252,237,94,65,256,100,197,274,168,188,246,126,265,114,233,196,261, +138,61,272,264,42,252,183,123,177,80,225,88,128,64,53,79,159,119,48,260, +29,36,142,218,282,268,196,109,215,105,84,66,167,70,43,210,36,227,47,213, +21,272,15,149,50,68,228,210,188,277,183,218,26,38,149,22,20,58,132,235, +164,216,14,45,286,58,255,36,286,15,249,20,1,264,170,51,46,112,262,235, +103,158,166,129,197,28,152,217,87,284,165,251,214,180,10,214,239,265,250,238, +281,213,259,282,191,142,47,238,255,22,186,71,180,65,201,90,94,66,21,181, +64,186,146,278,80,156,206,32,135,170,271,129,96,243,124,0,98,171,239,67, +193,138,138,87,204,52,178,11,118,199,193,183,99,52,174,179,209,94,212,58, +264,196,187,73,152,25,74,251,196,26,31,103,165,170,191,82,222,82,94,54, +282,1,237,95,54,125,275,263,219,200,34,196,110,222,270,262,247,58,227,157, +85,259,261,250,142,165,46,78,248,141,133,243,142,83,51,196,208,39,173,141, +240,207,51,63,143,34,39,103,93,267,260,178,240,234,142,96,113,189,174,74, +43,20,30,185,104,82,95,26,122,268,167,76,189,218,139,45,253,179,148,59, +160,122,238,113,70,93,209,183,282,97,257,39,117,1,224,222,84,32,248,206, +14,128,283,203,60,136,248,26,28,109,86,188,232,37,14,15,131,224,198,127}; + //Transmiters location array + + static short int grid[GRID_SIZE]; + + // Problem --------------------------------------------------------------- + + Problem::Problem ():_dimension(0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << "Number of Variables " << pbm._dimension + << endl; + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int i; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer,"%d",&pbm._dimension); + + return is; + } + + Problem& Problem::operator= (const Problem& pbm) + { + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if (_dimension!=pbm.dimension()) return false; + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + return maximize; + //return minimize; + } + + int Problem::dimension() const + { + return _dimension; + } + + Problem::~Problem() + {} + + // Solution -------------------------------------------------------------- + + Solution::Solution (const Problem& pbm):_pbm(pbm),_var(pbm.dimension()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + is >> sol._var[i]; + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().dimension();i++) + os << " " << sol._var[i]; + return os; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns << sol._var[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol._var.size();i++) + ns >> sol._var[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _var=sol._var; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () const + { + register int x,y,x1,y1,k; + double covered_points=0.0, cover_rate=0.0, fitness=0.0,alfa=2.0; + int used_trans; + + for (k=0;k<GRID_SIZE;k++) // Initializing the grid + grid[k]=0; + + + used_trans=0; // Updating covered points in the grid according ... + for (k=0;k<_var.size();k++) // with transmiter locations and calculating ... + { // covered points. + if (_var[k]!=0.0) + { + used_trans++; + x=trans_location[k*2]; + y=trans_location[k*2+1]; + for (x1=x-RANGE;x1<=x+RANGE;x1++) + for (y1=y-RANGE;y1<=y+RANGE;y1++) + if ((x1>=0)&(y1>=0)&(x1<GRID_SIZE_X)&(y1<GRID_SIZE_Y)) + { + grid[x1*GRID_SIZE_X+y1]++; + if (grid[x1*GRID_SIZE_X+y1]==1) covered_points++; + } + } + } + + cover_rate =(double) (100.0 * covered_points) / (GRID_SIZE); + fitness = (cover_rate * cover_rate )/used_trans; + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_var.get_first(); + } + + void Solution::to_Solution(char *_string_) + { + int *ptr=(int *)_string_; + for (int i=0;i<_pbm.dimension();i++) + { + _var[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return (_pbm.dimension() * sizeof(int)); + } + + + int& Solution::var(const int index) + { + return _var[index]; + } + + + Rarray<int>& Solution::array_var() + { + return _var; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + const float probability = 0.03; + + for (int i=0;i<sol.pbm().dimension();i++) + { + if (rand01()<=probability) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((int)solver.current_best_cost() == pbm.dimension()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/rnd/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/rnd/pgfileLan new file mode 100644 index 0000000..d85e66e --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/rnd/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan +localhost 1 ~/Mallba/rep/SA/rnd/MainLan diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/Config.cfg b/ProyectoFinal/CHC/malva/rep/SA/vrp/Config.cfg new file mode 100644 index 0000000..510e26d --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +../../../ProblemInstances/VRP-instances/vrpnc1.txt +res/vrp1.sa.lan.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/MainLan.cc b/ProyectoFinal/CHC/malva/rep/SA/vrp/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/MainLan.cc @@ -0,0 +1,53 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + char path[MAX_BUFFER]; + int len; + int longitud; + + system("clear"); + + get_path(argv[0],path); + len = strlen(path); + longitud = MAX_BUFFER - len; + + strcat(path,"Config.cfg"); + ifstream f(path); + if(!f) show_message(10); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f1(path); + if(!f1) show_message(11); + + f.getline(&(path[len]),longitud,'\n'); + ifstream f2(path); + if(!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + + Solver_Lan solver(pbm,cfg,argc,argv); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << "Solucion: " << solver.global_best_solution() << " Fitness: " << solver.global_best_solution().fitness(); + + f.getline(&(path[len]),longitud,'\n'); + ofstream fexit(path); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + cout << endl << endl << " :( ---------------------- THE END --------------- :) " << endl; + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/MainSeq.cc b/ProyectoFinal/CHC/malva/rep/SA/vrp/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/MainSeq.cc @@ -0,0 +1,42 @@ +#include "SA.hh" +#include <iostream.h> +#include <fstream.h> + +int main (int argc, char** argv) +{ + using skeleton SA; + + system("clear"); + + if(argc < 4) + show_message(1); + + ifstream f1(argv[1]); + if (!f1) show_message(11); + + ifstream f2(argv[2]); + if (!f2) show_message(12); + + Problem pbm; + f2 >> pbm; + + SetUpParams cfg; + f1 >> cfg; + + Solver_Seq solver(pbm,cfg); + solver.run(); + + if (solver.pid()==0) + { + solver.show_state(); + cout << solver.global_best_solution() + << " Fitness: " << solver.global_best_solution().fitness() << endl; + cout << "\n\n :( ---------------------- THE END --------------- :) "; + + ofstream fexit(argv[3]); + if(!fexit) show_message(13); + fexit << solver.userstatistics(); + + } + return(0); +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/Makefile b/ProyectoFinal/CHC/malva/rep/SA/vrp/Makefile new file mode 100644 index 0000000..cb3ba14 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/Makefile @@ -0,0 +1,22 @@ +include ../../../environment + +all: MainSeq MainLan + +clean: + rm -f MainLan MainSeq MainWan *.o *% *~ + +MainLan: SA.req.o SA.pro.o StopCondition.o MainLan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainWan: SA.req.o SA.pro.o StopCondition.o MainWan.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +MainSeq: SA.req.o SA.pro.o StopCondition.o MainSeq.o + $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(CPPFLAGS) -o $@ + +LAN: + $(RUN) -v -p4pg pgfileLan MainLan +WAN: + $(RUN) -v -p4pg pgfileWan MainWan +SEQ: + ./MainSeq SA.cfg ../../../ProblemInstances/VRP-instances/vrpnc1.txt res/vrp1.sa.seq.txt diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.cfg b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.cfg new file mode 100644 index 0000000..eed6739 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.cfg @@ -0,0 +1,9 @@ +10 // number of independent runs +1000 // number of evaluations +10 // Markov-Chain Length +.99 // temperature Decay +1 // display state ? +LAN-configuration +1001 // the global state is updated in this number of evaluations +0 // 0: asynchronized mode // 1: synchronized mode +10 // interval of iterations to cooperate ( if 0 no cooperation) diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.hh b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.hh new file mode 100644 index 0000000..845bb53 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.hh @@ -0,0 +1,499 @@ +#ifndef INC_SA +#define INC_SA + +#include "Mallba/mallba.hh" +#include "Mallba/States.hh" +#include "Mallba/Rarray.h" +#include "Mallba/time.hh" +#include "Mallba/netstream.hh" +#include <math.h> +#include <string.h> + +skeleton SA +{ + + provides class SetUpParams; + provides class Statistics; + provides class Move; + provides class StopCondition; + provides class Solver; + provides class Solver_Seq; + provides class Solver_Lan; + provides class Solver_Wan; + + requires class Problem; + requires class Solution; + requires class StopCondition_1; + requires class StopCondition_2; + requires class StopCondition_3; + requires class DefaultMove; + requires class UserStatistics; + requires bool TerminateQ (const Problem& pbm, const Solver& solver, const SetUpParams& setup); + +// Problem ---------------------------------------------------------------------------- + + requires class Problem + { + public: + Problem (); + ~Problem (); + + friend ostream& operator<< (ostream& os, const Problem& pbm); + friend istream& operator>> (istream& is, Problem& pbm); + + Problem& operator= (const Problem& pbm); + bool operator== (const Problem& pbm) const; + bool operator!= (const Problem& pbm) const; + + Direction direction () const; + + int nCustomers() const; + int capacity() const; + double maxRouteTime() const; + double bestCost() const; + double distance(const int i, const int j) const; + int demand(const int i) const; + int service_time() const; + + private: + void genDistances(int *x,int *y); + + int _nCustomers; + int _capacity; + double **_distance; + int _service_time; + double _maxRouteTime; + double _bestCost; + int *_demand; + }; + +//Solution ---------------------------------------------------------------------------- + + requires class Solution + { + public: + Solution (const Problem& pbm); + Solution (const Solution& sol); + ~Solution(); + + friend ostream& operator<< (ostream& os, const Solution& sol); + friend istream& operator>> (istream& is, Solution& sol); + friend NetStream& operator << (NetStream& ns, const Solution& sol); + friend NetStream& operator >> (NetStream& ns, Solution& sol); + + const Problem& pbm() const; + + Solution& operator= (const Solution& sol); + bool operator== (const Solution& sol) const; + bool operator!= (const Solution& sol) const; + + char *to_String() const; + void to_Solution(char *_vertex_); + unsigned int size() const; + + void initialize(); + double fitness () const; + + int & pos(const int index); + Rarray<int> & routes(); + void print(); + + private: + Rarray<int> _routes; + const Problem& _pbm; + }; + +// UserStatistics ---------------------------------------------------------------------------- + + requires class UserStatistics + { + private: + struct user_stat + { + unsigned int trial; + double initial_temperature; + double temperature_best_found_trial; + unsigned long nb_evaluation_best_found_trial; + double best_cost_trial; + float time_best_found_trial; + float time_spent_trial; + }; + + Rlist<struct user_stat> result_trials; + + public: + UserStatistics (); + ~UserStatistics(); + + friend ostream& operator<< (ostream& os, const UserStatistics& usertats); + + UserStatistics& operator= (const UserStatistics& userstats); + void update(const Solver& solver); + void clear(); + }; + +// Move ---------------------------------------------------------------------------------- + + provides class Move + { + public: + Move() {} + virtual ~Move() {} + + virtual void Apply(Solution& sol) const = 0; + }; + +// DefaultMove ---------------------------------------------------------------------------------- + + requires class DefaultMove: public Move + { + public: + DefaultMove(); + ~DefaultMove(); + + void Apply(Solution& sol) const; + }; + +// SetUpParams ------------------------------------------------------------------------------- + + provides class SetUpParams + { + private: + unsigned int _independent_runs; + unsigned long _max_evaluations; + unsigned int _MarkovChain_length; + double _temperature_decay; + bool _display_state; + + // for LAN execution configuration + unsigned long _refresh_global_state; + bool _synchronized; + unsigned int _cooperation; + + public: + SetUpParams (); + + friend ostream& operator<< (ostream& os, const SetUpParams& setup); + friend istream& operator>> (istream& is, SetUpParams& setup); + + const unsigned int independent_runs() const; + const unsigned long max_evaluations() const; + const unsigned int MarkovChain_length() const; + const double temperature_decay() const; + const bool display_state() const; + const unsigned long refresh_global_state() const; + const bool synchronized() const; + const unsigned int cooperation() const; + + void independent_runs(const unsigned int val); + void max_evaluations(const unsigned long val); + void MarkovChain_length(const unsigned int val); + void temperature_decay(const double val); + void display_state(const bool val); + void refresh_global_state(const unsigned long val); + void synchronized(const bool val); + void cooperation(const unsigned int val); + + ~SetUpParams(); + }; + +// Statistics --------------------------------------------------------------------------------- + + provides class Statistics + { + private: + struct stat + { + unsigned int trial; + unsigned long nb_evaluations; + double best_cost; + double current_cost; + }; + + Rlist<struct stat> stats_data; + + public: + Statistics(); + + friend ostream& operator<< (ostream& os, const Statistics& stats); + + Statistics& operator= (const Statistics& stats); + void update(const Solver& solver); + void clear(); + + ~Statistics(); + }; + +// Solver --------------------------------------------------------------------------------- + + provides class Solver + { + protected: + const Problem& problem; + const SetUpParams& params; + UserStatistics _userstat; + Statistics _stat; + Move* move; + Solution current; + double curfit; + Solution tentative; + double currentTemperature; + unsigned int k; // to control temperature update. + StateCenter _sc; + + float total_time_spent; + float time_spent_in_trial; + float start_trial; + float start_global; + + bool _end_trial; + + State_Vble _current_trial; + State_Vble _current_iteration; + State_Vble _current_best_solution; + State_Vble _current_best_cost; + State_Vble _current_solution; + State_Vble _current_cost; + + State_Vble _current_time_spent; + State_Vble _initial_temperature_trial; + State_Vble _time_best_found_trial; + State_Vble _iteration_best_found_trial; + State_Vble _temperature_best_found_trial; + State_Vble _time_spent_trial; + + State_Vble _trial_best_found; + State_Vble _iteration_best_found; + State_Vble _global_best_solution; + State_Vble _global_best_cost; + State_Vble _time_best_found; + + State_Vble _temperature; + State_Vble _display_state; + + const Direction _direction; + + bool AcceptQ(double tent, double cur, double temperature); + double Set_Initial_Temperature(const Problem& pbm); + void KeepHistory(const Solution& sol, const double curfit,const float time_spent_trial,const float total_time_spent); + + double UpdateT(double temp, int K); + + public: + // Constructor - Destructor ------------------------- + + Solver (const Problem& pbm, const SetUpParams& setup); + virtual ~Solver (); + virtual int pid() const; + bool end_trial() const; + + // Execution methods -------------------------------- + + // Full execution + virtual void run () =0; + virtual void run (unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol, unsigned long int nb_evaluations) =0; + + virtual void run (const double initialTemperature) =0; + virtual void run (const Solution& sol,const double initialTemperature) =0; + virtual void run (const double initialTemperature, unsigned long int nb_evaluations) =0; + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations) =0; + + // Partial execution + virtual void StartUp () =0; + virtual void StartUp (const Solution& sol) =0; + virtual void StartUp (const double initialTemperature) =0; + virtual void StartUp (const Solution& sol, const double initialTemperature) =0; + virtual void DoStep () =0; + + // Statistics handling ------------------------------ + + const Statistics& statistics() const; + const UserStatistics& userstatistics () const; + const SetUpParams& setup() const; + const Problem& pbm() const; + + // State handling ----------------------------------- + + void RefreshState(); + void UpdateFromState(); + StateCenter* GetState(); + + unsigned int current_trial() const; + unsigned long current_iteration() const; + Solution current_best_solution() const; + Solution current_solution() const; + double current_best_cost() const; + double current_cost() const; + float current_time_spent() const; + float time_best_found_trial() const; + double initial_temperature_trial() const; + unsigned int iteration_best_found_trial() const; + double temperature_best_found_trial() const; + float time_spent_trial() const; + unsigned int trial_best_found() const; + unsigned int iteration_best_found() const; + Solution global_best_solution() const; + double global_best_cost() const; + float time_best_found() const; + double temperature() const; + int display_state() const; + + void current_trial(const unsigned int value); + void current_iteration(const unsigned long value); + void current_best_solution(const Solution& sol); + void current_best_cost(const double value); + void current_solution(const Solution& sol); + void current_cost(const double value); + void current_time_spent(const float value); + void time_best_found_trial(const float value); + void initial_temperature_trial(const double temperature); + void iteration_best_found_trial(const unsigned int value); + void temperature_best_found_trial(const double value); + void time_spent_trial(const float value); + void trial_best_found(const unsigned int value); + void iteration_best_found(const unsigned int value); + void global_best_solution(const Solution& sol); + void global_best_cost(const double value); + void time_best_found(const float value); + void temperature(const double value); + void display_state(const int value); + void show_state() const; + + // State handling ----------------------------------- + void SetMove(Move* mov); + }; + + provides class Solver_Seq: public Solver + { + public: + // Constructor - Destructor ------------------------- + + Solver_Seq ( const Problem& pbm, const SetUpParams& setup); + virtual ~Solver_Seq (); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + }; + + provides class Solver_Lan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Lan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + + provides class Solver_Wan: public Solver + { + private: + NetStream _netstream; + int mypid; + + void send_local_state_to(int _mypid); + int receive_local_state_from(int source_pid); + + void check_for_refresh_global_state(); + + unsigned int _current_trial; + unsigned int _current_iteration; + double _best_cost_trial; + Solution _best_solution_trial; + float _time_best_found_in_trial; + unsigned int _iteration_best_found_in_trial; + double _temperature_best_found_in_trial; + + int cooperation(); + // Termination phase // + bool final_phase; + int acum_evaluations; + public: + Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv); + virtual ~Solver_Wan (); + virtual int pid() const; + NetStream& netstream(); + + // Execution methods -------------------------------- + + // Full execution + void run (); + virtual void run (unsigned long int max_evaluations); + virtual void run (const Solution& sol, unsigned long int max_evaluations); + + virtual void run (const double initialTemperature); + virtual void run (const Solution& sol,const double initialTemperature); + virtual void run (const double initialTemperature, unsigned long int nb_evaluations); + virtual void run (const Solution& sol,const double initialTemperature, unsigned long int nb_evaluations); + + // Partial execution + virtual void StartUp (); + virtual void StartUp (const Solution& sol); + virtual void StartUp (const double initialTemperature); + virtual void StartUp (const Solution& sol, const double initialTemperature); + virtual void DoStep (); + + void reset(); + }; + +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.pro.cc b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.pro.cc @@ -0,0 +1,1807 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** Provided classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +************************************************/ + +#include <iostream.h> +#include <math.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "Mallba/time.hh" + +skeleton SA +{ + +// SetUpParams ----------------------------------------------------------- + + SetUpParams::SetUpParams (): + _independent_runs(0), + _max_evaluations(0), + _MarkovChain_length(0), + _temperature_decay(0), + _refresh_global_state(0), + _synchronized(0), + _display_state(0), + _cooperation(0) + {} + + istream& operator>> (istream& is, SetUpParams& setup) + { + char buffer[MAX_BUFFER]; // current line in the setup file + char command[50]; + int op; + double dop; + short int nb_param=0; + short int nb_section=0; + short int nb_LAN_param=0; + + while (is.getline(buffer,MAX_BUFFER,'\n')) + { + sscanf(buffer," %s ",command); + + if (!(strcmp(command,"General"))) nb_section=0; + if (!(strcmp(command,"LAN-configuration"))) nb_section=1; + + if (nb_param==3 && nb_section==0) + { + dop=-1; + sscanf(buffer," %lf ",&dop); + if (dop<0) continue; + } + else + { + op=-1; + sscanf(buffer," %ld%*s ",&op); + if (op<0) continue; + } + + switch (nb_section) + { + case 0: switch (nb_param) + { + case 0: setup.independent_runs(op); break; + case 1: setup.max_evaluations(op); break; + case 2: setup.MarkovChain_length(op); break; + case 3: setup.temperature_decay(dop); break; + case 4: setup.display_state(op); break; + } + nb_param++; + break; + case 1: if (nb_LAN_param>=3) break; + if (nb_LAN_param==0) setup.refresh_global_state(op); + if (nb_LAN_param==1) setup.synchronized(op); + if (nb_LAN_param==2) setup.cooperation(op); + nb_LAN_param++; + break; + } // end switch + } // end while + return is; + } + + ostream& operator<< (ostream& os, const SetUpParams& setup) + { + os << "CONFIGURATION -------------------------------------------" << endl << endl; + os << "\t" << "Independent runs : " << setup.independent_runs() << endl + << "\t" << "Evaluation steps: " << setup.max_evaluations() << endl + << "\t" << "Markov-Chain Length: " << setup.MarkovChain_length() << endl + << "\t" << "Temperature Decay: " << setup.temperature_decay() << endl; + + if (setup.display_state()) + os << "\t" << "Display state" << endl; + else + os << "\t" << "Not display state" << endl; + os << endl << "\t" << "LAN configuration:" << endl + << "\t" << "----------------------" << endl << endl + << "\t" << "Refresh global state in number of generations: " << setup.refresh_global_state() << endl; + + if (setup.synchronized()) + os << "\t" << "Running in synchronous mode" << endl; + else + os << "\t" << "Running in asynchronous mode" << endl; + + if (!setup.cooperation()) + os << "\t" << "Running without cooperation" << endl << endl; + else + os << "\t" << "Running with cooperation in " << setup.cooperation() << " iterations. " << endl << endl; + + os << endl << endl << "END CONFIGURATION -------------------------------------------" << endl << endl; + return os; + } + + const unsigned int SetUpParams::independent_runs() const + { + return _independent_runs; + } + + const unsigned long SetUpParams::max_evaluations() const + { + return _max_evaluations; + } + + const unsigned int SetUpParams::MarkovChain_length() const + { + return _MarkovChain_length; + } + + const double SetUpParams::temperature_decay() const + { + return _temperature_decay; + } + + const bool SetUpParams::display_state() const + { + return _display_state; + } + + const unsigned long SetUpParams::refresh_global_state() const + { + return _refresh_global_state; + } + + const bool SetUpParams::synchronized() const + { + return _synchronized; + } + + const unsigned int SetUpParams::cooperation() const + { + return _cooperation; + } + + void SetUpParams::independent_runs(const unsigned int val) + { + _independent_runs = val; + } + + void SetUpParams::max_evaluations(const unsigned long val) + { + _max_evaluations= val; + } + void SetUpParams::MarkovChain_length(const unsigned int val) + { + _MarkovChain_length= val; + } + void SetUpParams::temperature_decay(const double val) + { + _temperature_decay= val; + } + + void SetUpParams::display_state(const bool val) + { + _display_state=val; + } + + void SetUpParams::refresh_global_state(const unsigned long val) + { + _refresh_global_state=val; + } + + void SetUpParams::synchronized(const bool val) + { + _synchronized=val; + } + + void SetUpParams::cooperation(const unsigned int val) + { + _cooperation=val; + } + + SetUpParams::~SetUpParams() + {} + +// Statistics ------------------------------------------------------ + + Statistics::Statistics() + {} + + ostream& operator<< (ostream& os, const Statistics& stats) + { + int j; + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF CURRENT TRIAL " << endl; + os << "------------------------------------------------------------------" << endl; + for (int i=0;i< stats.stats_data.size();i++) + { + os << endl + << " Evaluations: " << stats.stats_data[i].nb_evaluations + << " Best: " << stats.stats_data[i].best_cost + << " Current: " << stats.stats_data[i].current_cost; + } + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + Statistics& Statistics::operator= (const Statistics& stats) + { + stats_data = stats.stats_data; + return *this; + } + + void Statistics::update(const Solver& solver) + { + /* struct stat *new_stat; + if ((new_stat=(struct stat *)malloc(sizeof(struct stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluations= solver.current_iteration(); + new_stat->best_cost = solver.current_best_cost(); + new_stat->current_cost = solver.current_cost(); + stats_data.append(*new_stat); */ + } + + Statistics::~Statistics() + { + stats_data.remove(); + } + + void Statistics::clear() + { + stats_data.remove(); + } + +// Solver (superclass)--------------------------------------------------- + + Solver::Solver (const Problem& pbm, const SetUpParams& setup) + : problem(pbm), + params(setup), + _stat(), + _userstat(), + _sc(), + _direction(pbm.direction()), + current(pbm), + tentative(pbm), + currentTemperature(0.0), + time_spent_in_trial(0.0), + total_time_spent(0.0), + start_trial(0.0), + start_global(0.0), + _current_trial("_current_trial",_sc), + _current_iteration("_current_iteration",_sc), + _current_best_solution("_current_best_solution",_sc), + _current_best_cost("_current_best_cost",_sc), + _current_solution("_current_solution",_sc), + _current_cost("_current_cost",_sc), + _current_time_spent("_current_time_spent",_sc), + _initial_temperature_trial("_initial_temperature_trial",_sc), + _time_best_found_trial("_time_best_found_trial",_sc), + _iteration_best_found_trial("_iteration_best_found_trial",_sc), + _temperature_best_found_trial("_temperature_best_found_trial",_sc), + _time_spent_trial("_time_spent_trial",_sc), + _trial_best_found("_trial_best_found",_sc), + _iteration_best_found("_iteration_best_found;",_sc), + _global_best_solution("_global_best_solution",_sc), + _global_best_cost("_global_best_cost",_sc), + _time_best_found("_time_best_found",_sc), + _temperature("_temperature",_sc), + _display_state("_display_state",_sc) + { + current_trial(0); + current_iteration(0); + current_best_solution(current), + current_best_cost((-1) * pbm.direction() * infinity()); + current_solution(current); + current_cost((-1) * pbm.direction() * infinity()); + current_time_spent(total_time_spent); + initial_temperature_trial(0); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(0); + temperature_best_found_trial(0.0); + time_spent_trial(time_spent_in_trial); + trial_best_found(0); + iteration_best_found(0); + global_best_solution(current); + global_best_cost((-1) * pbm.direction() * infinity()); + time_best_found(total_time_spent); + temperature(currentTemperature); + display_state(setup.display_state()); + + move = new DefaultMove; + } + + int Solver::pid() const + { + return 0; + } + + bool Solver::end_trial() const + { + return _end_trial; + } + + unsigned int Solver::current_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_trial",(char *)&value, nitems, length); + return value; + } + + unsigned long Solver::current_iteration() const + { + unsigned long value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_iteration",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_best_solution() const + { + Solution sol(problem); + unsigned long nitems,length; + char data_stored[_current_best_solution.get_nitems() + _current_best_solution.get_length()]; + _sc.get_contents_state_variable("_current_best_solution", data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::current_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_best_cost",(char *)&value, nitems, length); + return value; + } + + double Solver::current_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_cost",(char *)&value, nitems, length); + return value; + } + + Solution Solver::current_solution() const + { + Solution sol(problem); + char data_stored[_current_solution.get_nitems() + _current_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_current_solution",data_stored, nitems, length); + sol.to_Solution((char *)data_stored); + return sol; + } + + float Solver::current_time_spent() const + { + float value=0.0; + unsigned long nitems,length; + _current_time_spent.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found_trial() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::initial_temperature_trial() const + { + double value=0.0; + unsigned long nitems,length; + _initial_temperature_trial.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature_best_found_trial() const + { + double value=0.0; + unsigned long nitems,length; + _temperature_best_found_trial.get_contents((char *)&value, nitems, length); + return value; + } + + float Solver::time_spent_trial() const + { + float value=0.0; + unsigned long nitems,length; + _time_spent_trial.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::trial_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _trial_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + unsigned int Solver::iteration_best_found() const + { + unsigned int value=0; + unsigned long nitems,length; + _iteration_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + Solution Solver::global_best_solution() const + { + Solution sol(problem); + char data_stored[_global_best_solution.get_nitems() + _global_best_solution.get_length()]; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_solution",data_stored, nitems, length); + sol.to_Solution(data_stored); + return sol; + } + + double Solver::global_best_cost() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_global_best_cost",(char *)&value, nitems, length); + return value; + } + + float Solver::time_best_found() const + { + float value=0.0; + unsigned long nitems,length; + _time_best_found.get_contents((char *)&value, nitems, length); + return value; + } + + double Solver::temperature() const + { + double value=0.0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_temperature",(char *)&value, nitems, length); + return value; + } + + int Solver::display_state() const + { + int value=0; + unsigned long nitems,length; + _sc.get_contents_state_variable("_display_state",(char *)&value, nitems, length); + return value; + } + + void Solver::current_trial(const unsigned int value) + { + _sc.set_contents_state_variable("_current_trial",(char *)&value,1,sizeof(int)); + } + + void Solver::current_iteration(const unsigned long value) + { + _sc.set_contents_state_variable("_current_iteration",(char *)&value,1,sizeof(long)); + } + + void Solver::current_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_best_cost(const double value) + { + _sc.set_contents_state_variable("_current_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_cost(const double value) + { + _sc.set_contents_state_variable("_current_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::current_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_current_solution",sol.to_String(),1,sol.size()); + } + + void Solver::current_time_spent(const float value) + { + _current_time_spent.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::time_best_found_trial(const float value) + { + _time_best_found_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::iteration_best_found_trial(const unsigned int value) + { + _iteration_best_found_trial.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::initial_temperature_trial(const double value) + { + _initial_temperature_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::temperature_best_found_trial(const double value) + { + _temperature_best_found_trial.set_contents((char *)&value,1,sizeof(double)); + } + + void Solver::time_spent_trial(const float value) + { + _time_spent_trial.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::trial_best_found(const unsigned int value) + { + _trial_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::iteration_best_found(const unsigned int value) + { + _iteration_best_found.set_contents((char *)&value,1,sizeof(int)); + } + + void Solver::global_best_solution(const Solution& sol) + { + _sc.set_contents_state_variable("_global_best_solution",sol.to_String(),1,sol.size()); + } + + void Solver::global_best_cost(const double value) + { + _sc.set_contents_state_variable("_global_best_cost",(char *)&value,1,sizeof(double)); + } + + void Solver::time_best_found(const float value) + { + _time_best_found.set_contents((char *)&value,1,sizeof(float)); + } + + void Solver::temperature(const double value) + { + _sc.set_contents_state_variable("_temperature",(char *)&value,1,sizeof(double)); + } + + void Solver::display_state(const int value) + { + _sc.set_contents_state_variable("_display_state",(char *)&value,1,sizeof(int)); + } + + const Statistics& Solver::statistics() const + { + return _stat; + } + + const UserStatistics& Solver::userstatistics() const + { + return _userstat; + } + + const SetUpParams& Solver::setup() const + { + return params; + } + + const Problem& Solver::pbm() const + { + return problem; + } + + void Solver::KeepHistory(const Solution& sol, const double curfit,const float time_spent_in_trial,const float total_time_spent) + { + bool betterG=false; + bool betterT=false; + + switch (_direction) + { + case minimize: betterG = (curfit < global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit < current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + case maximize: betterG = (curfit > global_best_cost() || (curfit == global_best_cost() && time_spent_in_trial < time_best_found())); + betterT = (curfit > current_best_cost() || (curfit == current_best_cost() && time_spent_in_trial < time_best_found_trial())); + break; + } + + if (betterT) + { + current_best_solution(sol); + current_best_cost(curfit); + time_best_found_trial(time_spent_in_trial); + iteration_best_found_trial(current_iteration()); + temperature_best_found_trial(temperature()); + if (betterG) + { + trial_best_found(current_trial()); + iteration_best_found(current_iteration()); + global_best_solution(sol); + global_best_cost(curfit); + time_best_found(time_spent_in_trial); + } + } + } + + double Solver::UpdateT(double temp, int K) + { + //return temp * params.temperature_decay(); // initial + + /* + if(K == 1) return temp/log(2); + else return temp * log(K) / log(K+1); + */ + /* + if(K == 1) return temp/2; + else return (temp * K) / (K + 1); + */ + + if(K == 1) return temp / exp(2); + else return (temp * exp(K)) / exp(K+1); + + } + + StateCenter* Solver::GetState() + { + return &_sc; + } + + void Solver::RefreshState() + { + current_solution(current); + current_cost(curfit); + current_time_spent(total_time_spent); + time_spent_trial(time_spent_in_trial); + temperature(currentTemperature); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::UpdateFromState() + { + current = current_solution(); + curfit = current_cost(); + total_time_spent=current_time_spent(); + time_spent_in_trial=time_spent_trial(); + currentTemperature = temperature(); + + KeepHistory(current,curfit,time_spent_in_trial,total_time_spent); + } + + void Solver::show_state() const + { + cout << endl << "Current trial: " << current_trial(); + cout << endl << "Current iteration: " << current_iteration(); + cout << endl << "Current Temperature: " << temperature (); + cout << endl << "Current cost: " << current_cost(); + cout << endl << "Best cost in trial: " << current_best_cost(); + cout << endl << "Time of best solution found in trial: " << time_best_found_trial(); + cout << endl << "Iteration of best solution found in trial: " << iteration_best_found_trial(); + cout << endl << "Initial temperature in trial: " << initial_temperature_trial(); + cout << endl << "Temperature of best solution found in trial: " << temperature_best_found_trial(); + cout << endl << "Time spent in trial: " << time_spent_trial(); + cout << endl << "Global best cost: " << global_best_cost(); + cout << endl << "Trial of best global solution found: " << trial_best_found(); + cout << endl << "Iteration of best global solution found: " << iteration_best_found(); + cout << endl << "Time of global best solution found: " << time_best_found(); + // cout << endl << "Current solution: " << current_solution(); + // cout << endl << "Best solution of trial: " << current_best_solution(); + // cout << endl << "Global solution: " << global_best_solution() << endl; + cout << endl << endl << "Current time spent (so far): " << current_time_spent() << endl; + } + + Solver::~Solver() + { + _sc.removeAll(); + delete move; + } + + bool Solver::AcceptQ (double tent, double cur, double temperature) + { + if (_direction==minimize) + + return (tent < cur) || + ((rand01()*(1+exp((tent-cur)/temperature)))<2.0); + + else + + return (tent > cur) || + ((rand01()*(1+exp((cur-tent)/temperature)))<2.0); + } + + double Solver::Set_Initial_Temperature(const Problem& pbm) + { + const double beta = 1.05; + const double test = 10; + const double acrat = .8; + const double T = 1.0; + + Solution current (pbm); + Solution newsol (pbm); + double ac; + double fit; + double temperature = T; + + do + { + temperature *= beta; + ac = 0; + current.initialize(); + fit = current.fitness(); + for (int i=0; i<test; i++) + { + newsol = current; + move->Apply(newsol); + if (AcceptQ(newsol.fitness(),fit,temperature)) + ac += 1.0/test; + } + } while (ac < acrat); + + initial_temperature_trial(temperature); + return temperature; + + } + + void Solver::SetMove (Move* mov) + { + delete move; + move = mov; + } + + // Solver sequencial ----------------------------------------------------- + + Solver_Seq::Solver_Seq (const Problem& pbm, const SetUpParams& setup) + : Solver(pbm,setup) + { + random_seed(time(0)); + _end_trial=true; + } + + Solver_Seq::~Solver_Seq () + {} + + void Solver_Seq::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Seq::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Seq::StartUp(const Solution& sol, const double initialTemperature) + { + start_trial=_used_time(); + start_global=total_time_spent; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current = sol; + curfit = current.fitness(); + current_best_cost((-1) * problem.direction() * infinity()); + currentTemperature = initialTemperature; + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + void Solver_Seq::DoStep() + { + current_iteration(current_iteration()+1); + + tentative = current; + move->Apply(tentative); + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + if (display_state()) + show_state(); + } + + + void Solver_Seq::run (unsigned long int max_evaluations) + { + StartUp(); + + while (current_iteration()<max_evaluations && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Seq::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + + while ((current_iteration()<max_evaluations) && !TerminateQ(problem, *this, params)) + DoStep(); + } + + void Solver_Seq::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + // Solver LAN ----------------------------------------------------------- + + Solver_Lan::Solver_Lan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Lan::~Solver_Lan () + { + NetStream::finalize(); + } + + int Solver_Lan::pid() const + { + return mypid; + } + + NetStream& Solver_Lan::netstream() + { + return _netstream; + } + + void Solver_Lan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Lan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Lan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + void update(Direction direction, Solution &solution_received,double cost_received, Solution &solution_to_send, double &best_cost) + { + switch (direction) + { + case minimize: if (cost_received < best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + case maximize: if (cost_received > best_cost) + { + solution_to_send=solution_received; + best_cost=cost_received; + } + } + } + + int Solver_Lan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Lan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Lan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Lan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Lan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Lan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Lan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Lan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Lan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } + + // Solver WAN ------------------------------------------------------------ + + Solver_Wan::Solver_Wan (const Problem& pbm, const SetUpParams& setup,int argc,char **argv): + _best_solution_trial(pbm), + Solver(pbm,setup),_netstream(), + // Termination phase // + final_phase(false),acum_evaluations(0) + { + NetStream::init(argc,argv); + mypid=_netstream.my_pid(); + random_seed(time(0) + (mypid+1)); + if (mypid!=0) + _netstream << set_source(0) << set_target(0); + } + + Solver_Wan::~Solver_Wan () + { + NetStream::finalize(); + } + + int Solver_Wan::pid() const + { + return mypid; + } + + NetStream& Solver_Wan::netstream() + { + return _netstream; + } + + void Solver_Wan::StartUp() + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const Solution& sol) + { + StartUp(sol, Set_Initial_Temperature(problem)); + } + + void Solver_Wan::StartUp(const double initialTemperature) + { + Solution sol(problem); + + sol.initialize(); + + StartUp(sol, initialTemperature); + } + + void Solver_Wan::StartUp(const Solution& sol, const double initialTemperature) + { + + _netstream << barrier; + + start_trial=_used_time(); + start_global=total_time_spent; + // Termination phase // + final_phase = false; + acum_evaluations = 0; + + _end_trial=false; + + current_trial(current_trial()+1); + current_iteration(0); + + k = 0; + time_spent_in_trial=0.0; + current_best_cost((-1) * problem.direction() * infinity()); + iteration_best_found_trial(0); + temperature_best_found_trial(0); + time_best_found_trial(0.0); + time_spent_trial(0.0); + + if (mypid!=0) + { + current = sol; + curfit = current.fitness(); + currentTemperature = initialTemperature; + + RefreshState(); + + send_local_state_to(mypid); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) show_state(); + } + } + + int Solver_Wan::cooperation() + { + int received=false; + Solution solution_received(problem), solution_to_send(problem); + double cost_received=0, cost_to_send=0; + int pending=false; + int pid_source,pid_target; + + if (mypid!=0) + { + if (((int)current_iteration() % params.refresh_global_state()) ==0) // isnot the server + { + _netstream << set_target(0); + send_local_state_to(mypid); + } + + if (params.cooperation()==0) return received; + pid_target=mypid+1; + if (pid_target==_netstream.pnumber()) pid_target=1; + _netstream << set_target(pid_target); + + pid_source=mypid-1; + if (pid_source==0) pid_source=_netstream.pnumber()-1; + _netstream << set_source(pid_source); + + if ((((int)current_iteration() % params.cooperation())==0) && (params.max_evaluations()!=current_iteration())) + { + if (mypid==1) + _netstream << current_best_cost() << current_best_solution(); + + if (params.synchronized()) + { + _netstream << wait(regular); + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (!params.synchronized()) + { + int pending=false; + _netstream._probe(regular,pending); + if (pending) + { + _netstream >> cost_received >> solution_received; + received=true; + } + } + + if (mypid!=1 && received) + { + solution_to_send = current_best_solution(); + cost_to_send=current_best_cost(); + + if (received) + { + update(problem.direction(),solution_received, cost_received, solution_to_send,cost_to_send); + } + _netstream << cost_to_send << solution_to_send; + } + + if (received) + { + tentative=solution_received; + curfit=cost_received; + } + + _netstream << set_target(0); + } + + return received; + } + + void Solver_Wan::DoStep() + { + current_iteration(current_iteration()+1); + // Termination phase // + _netstream << set_source(0); + int pending; + _netstream._probe(packed, pending); + if(pending) + { + Solution sol(problem); + _netstream << pack_begin >> sol << pack_end; + final_phase = true; + } + //////////////////////// + + int received=cooperation(); + + if (!received) + { + tentative = current; + move->Apply(tentative); + } + + double tentfit = tentative.fitness(); + + if (AcceptQ(tentfit,curfit, currentTemperature)) + { + current = tentative; + curfit = tentfit; + } + + k++; + if (k>=params.MarkovChain_length()) + { + currentTemperature = UpdateT(currentTemperature,current_iteration()/params.MarkovChain_length()); + k = 0; + } + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // if (display_state()) + // show_state(); + } + + void Solver_Wan::send_local_state_to(int _mypid) + { + _netstream << set_target(0); + _netstream << pack_begin + << _mypid + << current_trial() + << current_iteration() + << current_solution() + << current_cost() + << current_best_solution() + << current_best_cost() + << time_best_found_trial() + << iteration_best_found_trial() + << temperature_best_found_trial() + << temperature() + << pack_end; + } + + int Solver_Wan::receive_local_state_from(int source_pid) + { + _netstream << set_source(source_pid); + int received_pid=0; + + _netstream._wait(packed); + _netstream << pack_begin + >> received_pid + >> _current_trial + >> _current_iteration + >> current + >> curfit + >> _best_solution_trial + >> _best_cost_trial + >> _time_best_found_in_trial + >> _iteration_best_found_in_trial + >> _temperature_best_found_in_trial + >> currentTemperature + << pack_end; + + return received_pid; + } + + void Solver_Wan::check_for_refresh_global_state() // Executed in process with pid 0 + { + unsigned int nb_finalized_processes=0; + int received_pid; + int nb_proc=_netstream.pnumber(); + + while (!_end_trial) + { + // checking for all processes + + received_pid=0; + received_pid=receive_local_state_from(MPI_ANY_SOURCE); + + // refresh the global state with received data ( a local state ) + current_trial(_current_trial); + current_iteration(_iteration_best_found_in_trial); + temperature(_temperature_best_found_in_trial); + + KeepHistory(_best_solution_trial,_best_cost_trial,_time_best_found_in_trial,start_global + _time_best_found_in_trial); + + if (received_pid==-1) + { + // Termination phase // + if(!final_phase && TerminateQ(problem,*this,params)) + { + Solution sol(problem); + acum_evaluations = params.max_evaluations() * nb_finalized_processes; + for(int i = 1; i < _netstream.pnumber(); i++) + { + _netstream << set_target(i); + _netstream << pack_begin << sol << pack_end; + } + final_phase = true; + } + nb_finalized_processes++; + acum_evaluations += _iteration_best_found_in_trial; + } + + if (nb_finalized_processes==nb_proc-1) _end_trial=true; + + current_iteration(_current_iteration); + temperature(currentTemperature); + + time_spent_in_trial = _used_time(start_trial); + total_time_spent = start_global + time_spent_in_trial; + + RefreshState(); + + _stat.update(*this); + //_userstat.update(*this); + + // display current global state + if (display_state()) show_state(); + } // end while + + // Actualización de las estadísticas // Termination phase // + iteration_best_found_trial(acum_evaluations/(_netstream.pnumber()-1)); + + bool betterG=false; + double best_cost = current_best_cost(); + switch (problem.direction()) + { + case minimize: betterG = (best_cost < global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + case maximize: betterG = (best_cost > global_best_cost() || (best_cost == global_best_cost() && time_best_found_trial() <= time_best_found())); + break; + } + + if (betterG) + iteration_best_found(iteration_best_found_trial()); + + RefreshState(); + + _stat.update(*this); + _userstat.update(*this); + + // display the global state at the end of the current trial + if (display_state()) show_state(); + } + + void Solver_Wan::run () + { + while (current_trial() < params.independent_runs()) + run(params.max_evaluations()); + } + + void Solver_Wan::run (const unsigned long int max_evaluations) + { + StartUp(); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol, unsigned long int max_evaluations) + { + StartUp(sol); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature) + { + while (current_trial() < params.independent_runs()) + run(sol,initialTemperature,params.max_evaluations()); + } + + void Solver_Wan::run (const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::run (const Solution& sol,const double initialTemperature, unsigned long int max_evaluations) + { + StartUp(sol,initialTemperature); + if (mypid!=0) + { + while (!final_phase && (current_iteration() < max_evaluations) && !(TerminateQ(problem,*this,params))) + DoStep(); + send_local_state_to(-1); + } + else + { + check_for_refresh_global_state(); + } + + _netstream << barrier; + reset(); + } + + void Solver_Wan::reset() + { + Solution left_solution(problem); + double left_cost; + _netstream << set_source(MPI_ANY_SOURCE); + if (mypid!=0) + { + int pendingr = false; + int pendingp = false; + do + { + pendingr = false; + pendingp = false; + _netstream._probe(regular,pendingr); + _netstream._probe(packed,pendingp); + if (pendingr) _netstream >> left_cost >> left_solution; + if (pendingp) _netstream << pack_begin >> left_solution << pack_end; + } while (pendingr || pendingp); + } + _netstream << barrier; + } +}; + diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.req.cc b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.req.cc new file mode 100644 index 0000000..c14f23a --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/SA.req.cc @@ -0,0 +1,527 @@ +/************************************************ +*** *** +*** Simulated Annealing Skeleton v1.0 *** +*** User-required classes and methods *** +*** Developed by: Carlos Cotta Porras *** +*** *** +*** *** +************************************************/ + +#include <iostream.h> +#include "SA.hh" +#include "Mallba/random.hh" +#include "StopCondition.hh" + +skeleton SA { + + +// Problem --------------------------------------------------------------- + Problem::Problem ():_nCustomers(0),_capacity(0),_distance(NULL), + _demand(NULL),_service_time(0),_maxRouteTime(0.0) + {} + + ostream& operator<< (ostream& os, const Problem& pbm) + { + os << endl << endl << " Vehicle capacity: " << pbm._capacity + << endl << " Number of Customers: " << pbm._nCustomers << endl + << " Service time: " << pbm._service_time << endl + << " Max Time for any route: " << pbm._maxRouteTime << endl + << " Distances: " << endl; + + for(int i = 0; i < (pbm._nCustomers + 1) ; i++) + { + for(int j = 0; j < pbm._nCustomers; j++) + os << " " << pbm.distance(i,j); + os << endl; + } + + os << endl << " Demand for each customer: " << endl; + + for(int i = 0; i < (pbm._nCustomers + 1) ; i++) + { + os << " " << i << "\t" << pbm._demand[i] << endl; + } + + return os; + } + + istream& operator>> (istream& is, Problem& pbm) + { + char buffer[MAX_BUFFER]; + int *x; + int *y; + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d %lf %d %lf",&pbm._nCustomers,&pbm._capacity,&pbm._maxRouteTime,&pbm._service_time,&pbm._bestCost); + + if( ((pbm._distance = new double *[pbm._nCustomers + 1]) == NULL) + || ((pbm._demand = new int[pbm._nCustomers + 1]) == NULL) + || ((x = new int[pbm._nCustomers + 1]) == NULL) + || ((y = new int[pbm._nCustomers + 1]) == NULL)) + show_message(7); + + // Read depot coordenates + if( ((pbm._distance[0] = new double[pbm._nCustomers+1]) == NULL)) + show_message(7); + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d",&(x[0]),&(y[0])); + pbm._demand[0] = 0; + + // Read customers coordenates + for(int i = 1; i < (pbm._nCustomers + 1); i++) + { + if( ((pbm._distance[i] = new double[pbm._nCustomers+1]) == NULL)) + show_message(7); + + is.getline(buffer,MAX_BUFFER,'\n'); + sscanf(buffer," %d %d %d", &(x[i]),&(y[i]),&(pbm._demand[i])); + } + + pbm.genDistances(x,y); + + delete [] x; + delete [] y; + + return is; + } + + void Problem::genDistances(int *x,int *y) + { + for(int i = 0; i < (_nCustomers + 1); i++) + for(int j = 0; j < (_nCustomers +1) ; j++) + _distance[i][j] = sqrt( pow( (double) (x[j] - x[i]),2 ) + + pow( (double) (y[j] - y[i]),2 ) ) + _service_time ; + } + + Problem& Problem::operator= (const Problem& pbm) + { + if(_distance != NULL) + { + for(int i= 0;i < (_nCustomers+1); i++) + if(_distance[i] != NULL) delete [] _distance[i]; + delete [] _distance; + } + + if(_demand != NULL) delete [] _demand; + + if( ((_distance = new double*[pbm._nCustomers]) == NULL) + || ((_demand = new int[pbm._nCustomers + 1]) == NULL)) + show_message(7); + + _nCustomers = pbm.nCustomers(); + _capacity = pbm.capacity(); + _service_time = pbm.service_time(); + _maxRouteTime = pbm.maxRouteTime(); + + for(int i = 0; i < (_nCustomers+1); i++) + { + _demand[i] = pbm.demand(i); + + if( ((_distance[i] = new double[_nCustomers+1]) == NULL)) + show_message(7); + + for(int j = 0; j < (_nCustomers+1); i++) + { + _distance[i][j] = pbm.distance(i,j); + } + } + + return *this; + } + + bool Problem::operator== (const Problem& pbm) const + { + if( (_maxRouteTime != pbm.maxRouteTime()) || (_nCustomers != pbm.nCustomers()) + || (_capacity != pbm.capacity()) || (_service_time != pbm.service_time())) + return false; + + for(int i = 0; i < (_nCustomers+1); i++) + { + if(_demand[i] != pbm.demand(i)) + return false; + + for(int j = 0; j < (_nCustomers+1); i++) + { + if(distance(i,j) != pbm.distance(i,j)) return false; + } + } + + return true; + } + + bool Problem::operator!= (const Problem& pbm) const + { + return !(*this == pbm); + } + + Direction Problem::direction() const + { + //return maximize; + return minimize; + } + + double Problem::maxRouteTime() const + { + return _maxRouteTime; + } + + double Problem::bestCost() const + { + return _bestCost; + } + + int Problem::nCustomers() const + { + return _nCustomers; + } + + int Problem::capacity() const + { + return _capacity; + } + + double Problem::distance(const int i, const int j) const + { + return _distance[i][j]; + } + + int Problem::demand(const int i) const + { + return _demand[i]; + } + + int Problem::service_time() const + { + return _service_time; + } + + Problem::~Problem() + { + if(_distance != NULL) + { + for(int i= 0;i < (_nCustomers+1); i++) + if(_distance[i] != NULL) delete [] _distance[i]; + delete [] _distance; + } + + if(_demand != NULL) delete [] _demand; + + } + +// Solution -------------------------------------------------------------- + Solution::Solution (const Problem& pbm):_pbm(pbm),_routes(pbm.nCustomers()) + {} + + const Problem& Solution::pbm() const + { + return _pbm; + } + + Solution::Solution(const Solution& sol):_pbm(sol.pbm()) + { + *this=sol; + } + + istream& operator>> (istream& is, Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers(); i++) + { + is >> sol._routes[i]; + } + return is; + } + + ostream& operator<< (ostream& os, const Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers(); i++) + { + os << (sol._routes[i]<10?" ":"") << sol._routes[i] << " "; + } + + return os; + } + + void Solution::print() + { + int ultimo = 0; + double dist = 0.0; + int cap = _pbm.capacity(); + + register int c_actual; + register int i = 0; + + int nRoute = 1; + + cout << " Ruta " << nRoute << " = 0 "; + while(i < _pbm.nCustomers()) + { + c_actual = _routes[i]; + + if( ((dist + _pbm.distance(ultimo,c_actual) + _pbm.distance(c_actual,0)) > _pbm.maxRouteTime()) + || (( cap - _pbm.demand(c_actual)) < 0) + // add in version 1.0.1 + || ((_pbm.distance(ultimo,0) + _pbm.distance(0,c_actual)) < _pbm.distance(ultimo,c_actual)) + ) + { + nRoute++; + cout << "0 -> dist = " << (dist + _pbm.distance(ultimo,0)) << " capacidad sobra = " << cap + << endl << "Ruta " << nRoute << " = 0 "; + ultimo = 0; + dist = 0.0; + cap = _pbm.capacity(); + } + else + { + dist += _pbm.distance(ultimo,c_actual); + cap -= _pbm.demand(c_actual); + ultimo = c_actual; + cout << ultimo << " "; + i++; + } + } + + cout << "0 -> dist = " << (dist + _pbm.distance(ultimo,0)) << " capacidad sobra = " << cap + << endl; + } + + NetStream& operator << (NetStream& ns, const Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers();i++) + ns << sol._routes[i]; + return ns; + } + + NetStream& operator >> (NetStream& ns, Solution& sol) + { + for (int i=0;i<sol.pbm().nCustomers();i++) + ns >> sol._routes[i]; + return ns; + } + + Solution& Solution::operator= (const Solution &sol) + { + _routes = sol._routes; + return *this; + } + + bool Solution::operator== (const Solution& sol) const + { + if (sol.pbm() != _pbm) return false; + return true; + } + + bool Solution::operator!= (const Solution& sol) const + { + return !(*this == sol); + } + + void Solution::initialize() + { + int aux,ind1,ind2; + + int max = _pbm.nCustomers(); + + for(int i = 0; i < max; i++) + _routes[i] = i+1; + + cout << endl; + + for(int i=0;i< (max*5) ; i++) + { + ind1 = rand_int(0,max-1); + ind2 = rand_int(0,max-1); + + aux = _routes[ind1]; + _routes[ind1] = _routes[ind2]; + _routes[ind2] = aux; + } + } + + double Solution::fitness () const + { + double fitness = 0.0; + int ultimo = 0; + double dist = 0.0; + int cap = _pbm.capacity(); + + register int c_actual; + register int i = 0; + + while(i < _pbm.nCustomers()) + { + c_actual = _routes[i]; + + if( ((dist + _pbm.distance(ultimo,c_actual) + _pbm.distance(c_actual,0)) > _pbm.maxRouteTime()) + || (( cap - _pbm.demand(c_actual)) < 0) + // Add on version 1.0.1 + // New constrains: cost( Route + actual) < cost( new Route(actual)) + || ((_pbm.distance(ultimo,0) + _pbm.distance(0,c_actual)) < _pbm.distance(ultimo,c_actual)) + ) + { + fitness += dist + _pbm.distance(ultimo,0); + ultimo = 0; + dist = 0.0; + cap = _pbm.capacity(); + } + else + { + dist += _pbm.distance(ultimo,c_actual); + cap -= _pbm.demand(c_actual); + ultimo = c_actual; + i++; + } + } + + fitness += dist + _pbm.distance(ultimo,0); + + return fitness; + } + + char *Solution::to_String() const + { + return (char *)_routes.get_first(); + } + + void Solution::to_Solution(char *_routes_) + { + int *ptr=(int *)_routes_; + + for (int i=0;i<_pbm.nCustomers();i++) + { + _routes[i]=*ptr; + ptr++; + } + } + + unsigned int Solution::size() const + { + return ( _pbm.nCustomers() * sizeof(int)); + } + + int & Solution::pos(const int index) + { + return _routes[index]; + } + + + Rarray<int>& Solution::routes() + { + return _routes; + } + + Solution::~Solution() + {} + +// UserStatistics ------------------------------------------------------- + + UserStatistics::UserStatistics () + {} + + ostream& operator<< (ostream& os, const UserStatistics& userstat) + { + os << "\n---------------------------------------------------------------" << endl; + os << " STATISTICS OF TRIALS " << endl; + os << "------------------------------------------------------------------" << endl; + + for (int i=0;i< userstat.result_trials.size();i++) + { + os << endl + << "\t" << userstat.result_trials[i].trial + << "\t" << userstat.result_trials[i].best_cost_trial + << "\t\t" << userstat.result_trials[i].nb_evaluation_best_found_trial + << "\t\t" << userstat.result_trials[i].initial_temperature + << "\t\t" << userstat.result_trials[i].temperature_best_found_trial + << "\t\t" << userstat.result_trials[i].time_best_found_trial + << "\t\t" << userstat.result_trials[i].time_spent_trial; + } + + os << endl << "------------------------------------------------------------------" << endl; + return os; + } + + + UserStatistics& UserStatistics::operator= (const UserStatistics& userstats) + { + result_trials=userstats.result_trials; + return (*this); + } + + + void UserStatistics::update(const Solver& solver) + { + if ((solver.pid()!=0) || (solver.end_trial()!=true) + || ((solver.current_iteration()!=solver.setup().max_evaluations()) + && !TerminateQ(solver.pbm(),solver,solver.setup()))) + return; + struct user_stat *new_stat; + if ((new_stat=(struct user_stat *)malloc(sizeof(struct user_stat)))==NULL) + show_message(7); + new_stat->trial = solver.current_trial(); + new_stat->nb_evaluation_best_found_trial= solver.iteration_best_found_trial(); + new_stat->initial_temperature=solver.initial_temperature_trial(); + new_stat->temperature_best_found_trial=solver.temperature_best_found_trial(); + new_stat->best_cost_trial = solver.current_best_cost(); + new_stat->time_best_found_trial= solver.time_best_found_trial(); + new_stat->time_spent_trial = solver.time_spent_trial(); + result_trials.append(*new_stat); + } + + void UserStatistics::clear() + { + result_trials.remove(); + } + + UserStatistics::~UserStatistics() + { + result_trials.remove(); + } + +// DefaultMove ------------------------------------------------------- + + + DefaultMove::DefaultMove() + {} + + DefaultMove::~DefaultMove() + {} + + void DefaultMove::Apply (Solution& sol) const + { + Solution aux(sol); + const int max = sol.pbm().nCustomers(); + float fit = sol.fitness(); + float fit_a; + Direction d = sol.pbm().direction(); + + for(int i = 0; i < max; i++) + for(int j = i+1; j < max; j++) + { + aux.routes().invert(i,j); + fit_a = aux.fitness(); + if( ((d == minimize) && (fit_a < fit)) + || ((d == minimize) && (fit_a > fit) && (rand01() < 0.3)) + || ((d == maximize) && (fit_a > fit)) + || ((d == maximize) && (fit_a < fit) && (rand01() < 0.3))) + { + fit = fit_a; + sol = aux; + } + else aux = sol; + } + } + + //------------------------------------------------------------------------ + // Specific methods ------------------------------------------------------ + //------------------------------------------------------------------------ + + bool TerminateQ (const Problem& pbm, const Solver& solver, + const SetUpParams& setup) + { + + StopCondition_3 stop; + return stop.EvaluateCondition(pbm,solver,setup); + } +} + + diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.cc b/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.cc new file mode 100644 index 0000000..e5a2279 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.cc @@ -0,0 +1,52 @@ +#include "StopCondition.hh" +skeleton SA +{ + +// StopCondition ------------------------------------------------------------------------------------- + + StopCondition::StopCondition() + {} + + StopCondition::~StopCondition() + {} + +// StopCondition_1 ------------------------------------------------------------------------------------- + + StopCondition_1::StopCondition_1():StopCondition() + {} + + bool StopCondition_1::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return false; + } + + StopCondition_1::~StopCondition_1() + {} + +// StopCondition_2 ------------------------------------------------------------------------------------- + + StopCondition_2::StopCondition_2():StopCondition() + {} + + bool StopCondition_2::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return (solver.global_best_cost()>8.5); + } + + StopCondition_2::~StopCondition_2() + {} + +// StopCondition_3 ------------------------------------------------------------------------------------- + + StopCondition_3::StopCondition_3():StopCondition() + {} + + bool StopCondition_3::EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup) + { + return ((double)solver.current_best_cost()==pbm.bestCost()); + } + + StopCondition_3::~StopCondition_3() + {} + +} diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.hh b/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/StopCondition.hh @@ -0,0 +1,41 @@ +#ifndef stop_condition +#define stop_condition + +#include "SA.hh" +skeleton SA +{ + + provides class StopCondition + { + public: + StopCondition(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup)=0; + ~StopCondition(); + }; + + requires class StopCondition_1 : public StopCondition + { + public: + StopCondition_1(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_1(); + }; + + requires class StopCondition_2 : public StopCondition + { + public: + StopCondition_2(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_2(); + }; + + requires class StopCondition_3 : public StopCondition + { + public: + StopCondition_3(); + virtual bool EvaluateCondition(const Problem& pbm,const Solver& solver,const SetUpParams& setup); + ~StopCondition_3(); + }; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/rep/SA/vrp/pgfileLan b/ProyectoFinal/CHC/malva/rep/SA/vrp/pgfileLan new file mode 100644 index 0000000..1c419a1 --- /dev/null +++ b/ProyectoFinal/CHC/malva/rep/SA/vrp/pgfileLan @@ -0,0 +1,5 @@ +localhost 0 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan +localhost 1 ~/Mallba/rep/SA/vrp/MainLan diff --git a/ProyectoFinal/CHC/malva/src/Makefile b/ProyectoFinal/CHC/malva/src/Makefile new file mode 100644 index 0000000..b6d64fb --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/Makefile @@ -0,0 +1,14 @@ +include ../environment + +OBJS = States.o netstream.o + +all: $(OBJS) + +States.o: States.cc States.hh + $(CXX) $(CPPFLAGS) States.cc -c + +netstream.o: netstream.cc netstream.hh + $(CXX) $(CPPFLAGS) netstream.cc -c + +clean: + rm -f *.o *~ *% diff --git a/ProyectoFinal/CHC/malva/src/Matrix.hh b/ProyectoFinal/CHC/malva/src/Matrix.hh new file mode 100644 index 0000000..cc30ae7 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/Matrix.hh @@ -0,0 +1,337 @@ +/***************************************************************************** +*** *** +*** Este fichero decribe el template Matrix, para el manejo de matrices. *** +*** Tambien permite el manejo de vectores, los que trata como matrices cuya*** +*** primera dimension es 1. *** +*** *** +*****************************************************************************/ +#ifndef _MATRIX +#define _MATRIX + +#include "Messages.h" +#include <assert.h> + +template <class T> class Matrix +{ + private: + T *_matrix; + T nulo,neutro,inverso; + int _dimX,_dimY; + + public: + Matrix() + { + _dimX = _dimY = 0; + _matrix = NULL; + } + + Matrix(const int x,const int y,const T nulo = 0.0,const T neutro = 1.0,const T inverso = -1.0) + { + assert(x >= 1); + assert(y >= 1); + + int k = 0; + + _dimX = x; + _dimY = y; + + this->nulo = nulo; + this->neutro = neutro; + this->inverso = inverso; + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < x; i++) + { + for(int j = 0; j < y ; j++) + { + _matrix[k] = (i!=j?nulo:neutro); + k++; + } + + } + } + + Matrix(const int y,const T nulo = 0.0,const T neutro = 1.0,const T inverso = -1.0) + { + assert(y >= 1); + + _dimX = 1; + _dimY = y; + + this->nulo = nulo; + this->neutro = neutro; + this->inverso = inverso; + + _matrix = new T [_dimY]; + if(!_matrix) show_message(7); + + _matrix[0] = neutro; + for(int j = 1; j < y ; j++) + _matrix[j] = nulo; + } + + Matrix(const Matrix<T> &m) + { + + _dimX = m.dimX(); + _dimY = m.dimY(); + + nulo = m.nulo; + neutro = m.neutro; + inverso = m.inverso; + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < (_dimX*_dimY); i++) + { + _matrix[i] = m[i]; + } + } + + + ~Matrix() + { + remove(); + } + + T &operator()(const int x,const int y) const + { + if((x >= _dimX) || (y >= _dimY)) + show_message(14); + + return (T&)(*(_matrix + (x*_dimX) + y)); + } + + T &operator[](const int y) const + { + if(y >= (_dimX*_dimY)) + show_message(14); + + return (T&)(*(_matrix + y)); + } + + T &operator()(const int y) const + { + if(y >= (_dimX*_dimY)) + show_message(14); + + return (T&)(*(_matrix + y)); + } + + Matrix<T> &operator=(const Matrix<T> &m) + { + remove(); + + _dimX = m.dimX(); + _dimY = m.dimY(); + + _matrix = new T [_dimX*_dimY]; + if(!_matrix) show_message(7); + + for(int i = 0; i < (_dimX*_dimY); i++) + { + _matrix[i] = m[i]; + } + + return (*this); + } + + bool operator==(const Matrix<T> &m) const + { + if((_dimX != m.dimX()) || (_dimY != m.dimY())) + return false; + + for(int i = 0; i < (_dimX*_dimY); i++) + if(_matrix[i] != m[i]) return false; + + return true; + } + + bool operator!=(const Matrix<T> &m) const + { + return !((*this) == m); + } + + Matrix<T> operator*(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimY?0:_dimX); + int y = (x!=0?m.dimY():0); + T acum = nulo; + + Matrix<T> res(x,y); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < m.dimY(); j++) + { + acum = nulo; + for( int k = 0; k < _dimY; k++) + acum += (*this)(i,k)* m(k,j); + res(i,j) = acum; + } + + return Matrix<T>(res); + + } + + Matrix<T> &operator*=(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimY?0:_dimX); + int y = (x!=0?0:m.dimY()); + T acum = nulo; + + Matrix<T> res(x,y); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < m.dimY(); j++) + { + acum = nulo; + for( int k = 0; k < _dimY; k++) + acum += (*this)(i,k)*m(k,j); + res(i,j) = acum; + } + + (*this) = res; + + return (*this); + + } + + Matrix<T> operator*(const T &elem) + { + Matrix<T> res(_dimX,_dimY); + + for(int i = 0; i < (_dimX*_dimY); i++) + res[i] = _matrix[i] * elem; + + return Matrix(res); + } + + Matrix<T> &operator*=(const T &elem) + { + for(int i = 0; i < (_dimX*_dimY); i++) + _matrix[i] *= elem; + + return (*this); + } + + Matrix<T> operator+(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimX?0:_dimX); + int y = (m.dimY()!=_dimY?0:_dimY); + + Matrix<T> res(x,y); + + for(int i = 0; i < (x*y); i++) + res[i] = _matrix[i] + m[i]; + + return Matrix<T>(res); + } + + Matrix<T> &operator+=(const Matrix<T> &m) + { + int x = (m.dimX()!=_dimX?0:_dimX); + int y = (m.dimY()!=_dimY?0:_dimY); + + for(int i = 0; i < (x*y); i++) + _matrix[i] += m[i]; + + return (*this); + } + + Matrix<T> operator-(const Matrix<T> &m) + { + Matrix<T> res(); + + res = m * inverso; + return (*this) + res; + } + + + Matrix<T> &operator-=(const Matrix<T> &m) + { + Matrix<T> res(); + + res = m * inverso; + (*this) += res; + + return (*this); + } + + Matrix<T> Traspuesta() + { + Matrix<T> res(_dimY,_dimX); + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < _dimY; j++) + res(j,i) = (*this)(i,j); + + return Matrix<T>(res); + } + + Matrix<T> &nula() + { + for(int i = 0; i < (_dimX*dimY); i++) + _matrix[i] = nulo; + + return (*this); + } + + Matrix<T> &identity() + { + register int k = 0; + + for(int i = 0; i < _dimX; i++) + for(int j = 0; j < _dimY; j++) + { + _matrix[k] = (i!=j?nulo:neutro); + k++; + } + + return (*this); + } + + unsigned int size() const + { + return (sizeof(T)*_dimX*_dimY); + } + + char *to_string() const + { + return (char *) _matrix; + } + + Matrix<T> &to_Matrix(char *_cadena) + { + T *ptr = (T *)_cadena; + + for(int i = 0; i < (_dimX*_dimY) ; i++) + { + _matrix[i] = *ptr; + ptr++; + } + + return (*this); + } + + + int dimX() const + { + return _dimX; + } + + int dimY() const + { + return _dimY; + } + + void remove() + { + if(_matrix != NULL) + delete [] _matrix; + } +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/src/Messages.h b/ProyectoFinal/CHC/malva/src/Messages.h new file mode 100644 index 0000000..e46b1d8 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/Messages.h @@ -0,0 +1,112 @@ +/*****************************************************************************/ +/*** ***/ +/*** Modificado por G.J.L.P. ***/ +/*** Añadidos nuevos mensajes que indican falta de algún ***/ +/*** Fichero de Configuración (No específico para ningún ***/ +/*** problema) o nuevos errores. ***/ +/*** ***/ +/*****************************************************************************/ + +#ifndef RLFAP_MESSAGES +#define RLFAP_MESSAGES + +#ifndef MAX_BUFFER +#define MAX_BUFFER 200 +#endif + +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +using namespace std; + +inline void show_message(int value) +{ + switch (value) + { + case 1: cout << endl << "Error: number of arguments in the execution call is incorrect !!" + << endl; break; + case 2: cout << endl << "Error: It's imposible find Configuration file !!" << endl; + break; + /* Específicos de RLFAP */ + case 3: cout << endl << "Error: It is imposible find the Celar problem definition file (cst.txt) !!" + << endl; break; + case 4: cout << endl << "Error: It is imposible find the Celar domains file (dom.txt) !!" + << endl; break; + case 5: cout << endl << "Error: It is imposible find the Celar links file (var.txt) !!" + << endl; break; + case 6: cout << endl << "Error: It is imposible find the Celar constraints file (ctr.txt) !!" + << endl; break; + /* Fallos de Memoria */ + case 7: cout << endl << "Error: No avalible memory for \"malloc\" operation !!" << endl; + break; + case 8: cout << endl << "Error: in \"free\" operation !!" << endl; + break; + /* Específicos del MaxCut */ + case 9: cout << endl << "Error: It is imposible find the Maxcut file (Maxcut.txt) !!" + << endl; break; + /* Genéricos de Falta de ficheros de configuracion adicionales al mensaje 2 */ + case 10: cout << endl << "Error: It's imposible find Configuration file (Config.cfg) !!" + << endl; break; + case 11: cout << endl << "Error: It's imposible find Skeleton Configuration File (Ske.cfg) !!" + << endl; break; + case 12: cout << endl << "Error: It's imposible find Instance Problem File !!" << endl; + break; + case 13: cout << endl << "Error: It's imposible find Resultate File !!" << endl; + break; + case 14: cout << endl << "Error: Index out of Range !!" << endl; + break; + default: cout << endl << "Unkown Error !!" << endl; + } + + cout << endl << " " << endl; + exit(-1); +} + +inline void continue_question() +{ + fflush(stdout); + cout << endl << "Press any key to continue..." << endl; + fflush(stdin); + getc(stdin); +} + +inline void get_path(const char *source,char *target) +{ + int last = 0; + + for(int i = 0; i < strlen(source); i++) + { + target[i] = source[i]; + if(target[i] == '/') + last = i; + } + target[last+1] = '\0'; +} + +inline unsigned count_lines(char *file_name) // returns the number of lines of a file +{ + char line[MAX_BUFFER]; + FILE *file; + int count=0; + + if ((file=fopen(file_name,"r"))==NULL) + { + fflush(stdout); + printf("File not found !"); + } + + while (!feof(file)) + { + if (fgets(line,MAX_BUFFER,file)) count++; + else + { + fclose(file); + break; + } + } + return count; +} + +#endif diff --git a/ProyectoFinal/CHC/malva/src/Rarray.h b/ProyectoFinal/CHC/malva/src/Rarray.h new file mode 100644 index 0000000..5d1a1c2 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/Rarray.h @@ -0,0 +1,145 @@ +/****************************************************************************** +*** *** +*** Template para el manejo dinámico de arrays *** +*** Añadido métodos para invertir todo o parte del array. *** +*** *** +******************************************************************************/ + +#ifndef ARRAY_INC +#define ARRAY_INC 1 +#include <iostream> +#include <assert.h> + +using namespace std; + +template<class E1> class Rarray +{ + private: + E1 *first; + int count; + + public: + Rarray() + { + first = NULL; + count = 0; + } + + ~Rarray() + { + remove(); + } + + E1* get_first() const + { + return first; + } + + void message_a(int cod) const + { + switch (cod) + { + case 1: cout << endl << "The size of array must be upper that 0 !!!" ; + } + } + + Rarray(const int size_a) + { + if (size_a<0) message_a(1); + first = new E1[size_a]; + count=size_a; + } + + void remove() + { + if (count!=0) + delete [] first; + } + + int size() const + { + return count; + } + + E1& operator[](int pos) const + { + return (E1&)(*(first + pos)); + } + + friend ostream& operator<< (ostream& os,const Rarray<E1>& a) + { + for (int i=0;i<a.size();i++) + os << endl << a[i]; + return os; + } + + Rarray<E1>& operator=(const Rarray<E1>& source) + { + remove(); + count = source.size(); + first = new E1[count]; + + for (int i=0;i<count;i++) + (*this)[i] = source[i]; + + return (*this); + } + + + Rarray<E1>& invert() + { + return invert(0,count-1); + } + + Rarray<E1>& invert(const int pos1, const int pos2) + { + int max,min,half,i,j; + E1 aux; + + if(pos1 > pos2) + { + max = pos1; + min = pos2; + } + else + { + max = pos2; + min = pos1; + } + + assert((min > 0) || (min < count-1)); + half = ((max-min)/2) + 1; + + for(i = min,j=max; i< half; i++,j--) + { + aux = first[min]; + first[min] = first[max]; + first[max] = aux; + } + + return (*this); + } + + Rarray<E1>& sort(int (*comp)(const E1 &,const E1 &)) + { + E1 aux; + int j; + + for (int i=1; i < count ; i++) + { + aux = first[i]; + j = i - 1; + while ( (comp(aux,first[j])) && (j >= 0) ) + { + first[j+1]= first[j]; + j--; + } + first[j+1] = aux; + } + + return (*this); + } + +}; // end of class + +#endif diff --git a/ProyectoFinal/CHC/malva/src/Rlist.h b/ProyectoFinal/CHC/malva/src/Rlist.h new file mode 100644 index 0000000..f561d0b --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/Rlist.h @@ -0,0 +1,415 @@ +/****************************************************************************** +*** *** +*** Este template sirve para el manejo de listas din�micas *** +*** *** +******************************************************************************/ + +#ifndef LIST_INC +#define LIST_INC 1 +#include <iostream> +#include <stdlib.h> +#include <Messages.h> + +using namespace std; + +template<class E> class Rlist_item +{ + public: + E *useful_data; // pointer to the structure stored in the list + Rlist_item<E> *next; + Rlist_item<E> *previous; + + Rlist_item(E& new_data) + { + useful_data=&new_data; + next=NULL; + previous=NULL; + } + + Rlist_item(E *new_data) + { + useful_data=new_data; + next=NULL; + previous=NULL; + } + + ~Rlist_item() + { + } + + Rlist_item<E>& next_item() + { + return *(next); + } + + Rlist_item<E>& previous_item() + { + return *(previous); + } + + bool is_last() + { + return (next==NULL); + } + + bool is_first() + { + return (previous==NULL); + } + + E& data() + { + return *(useful_data); + } +}; + +template<class E> class Rlist +{ + private: + Rlist_item<E> *first; // first item in the list + Rlist_item<E> *last; // last item un the list + int count; // number of items in the list + + public: + // constructor + Rlist() + { + first=NULL; + last=NULL; + count=0; + } + + // destructor + ~Rlist() + { + remove(); + } + + // Return the size of the list + int size() const + { return count; } + + // Go back to the initial state of the list + void reset() + { + first=NULL; + last=NULL; + count=0; + } + + // Add a item at the final of the list + Rlist<E>& append(E& new_item) + { + Rlist_item<E> *new_Rlist_item=new Rlist_item<E>(new_item); + if (first==NULL) + { + first=new_Rlist_item; + new_Rlist_item->next=NULL; + new_Rlist_item->previous=NULL; + } + else + { + last->next=new_Rlist_item; + new_Rlist_item->previous=last; + } + last=new_Rlist_item; + count++; + return *this; + } + + Rlist<E>& append(E *new_item) + { + append(*new_item); + return (*this); + } + + // Add a item in a position ( pos ) of the list + Rlist<E>& add_pos(E& new_item, const int pos) + { + if (pos==size()-1) + return append(new_item); + + if (pos==-1) + return add(new_item,NULL); + else + return add(new_item,get_at(pos).useful_data); + } + + // Add a item in the list in the position next to "previous item" + Rlist<E>& add(E& new_item,E *previous_item) + { + if (first==NULL) + return append(new_item); + + Rlist_item<E> *new_Rlist_item=new Rlist_item<E>(new_item); + + if (previous_item==NULL) // Add the item like the first of the list + { + new_Rlist_item->next=first; + new_Rlist_item->previous=NULL; + first->previous=new_Rlist_item; + first=new_Rlist_item; + } + else + { + int previous_position=get_position(*previous_item); + if (previous_position==-1) return(*this); + Rlist_item<E> *previous_Rlist_item = &( get_at(previous_position)); + new_Rlist_item->next=previous_Rlist_item->next; + new_Rlist_item->previous=previous_Rlist_item; + if (previous_Rlist_item->next!=NULL) + (previous_Rlist_item->next)->previous=new_Rlist_item; + else last=new_Rlist_item; + previous_Rlist_item->next=new_Rlist_item; + } + count++; + return *this; + } + + // Return a pointer to the first item of the list + Rlist_item<E> *get_first() const + { return first; } + + // Assign a item like the first item in the list + void set_first(Rlist_item<E> *new_first) + { first=new_first; } + + // Return a pointer to the last item of the list + Rlist_item<E> *get_last() const + { return last; } + + // Assign a item like the last item in the list + void set_last(Rlist_item<E> *new_last) + { last=new_last; } + + // Return the item at position "pos" + E& operator[](int pos) const + { + return *(get_at(pos).useful_data); + } + + // Return the Rlist_item at position "pos" + Rlist_item<E>& get_at(int pos) const + { + Rlist_item<E> *present=first; + for (int k=0;k<size();k++) + if (k==pos) return *present; + else present=present->next; + } + + // Return the item position in the list + int get_position(const E& item) const // probado + { + Rlist_item<E> *present=first; + int i=0; + + while(present!=NULL) + { + if (present->useful_data==&item) return i; + i++; + present=present->next; + } + return -1; // the object has not been found + } + + // Delete a item of the list + Rlist<E>& delete_item(E& item) + { + int position = get_position(item); + + if (position==-1) return *this; + Rlist_item<E> *present=&(get_at(position)); + + if (&item==first->useful_data) // is the first + { + if (&item==last->useful_data) + { + delete(first->useful_data); + delete(first); + first=NULL; + last=NULL; + count=0; + } + else + { + first=first->next; + first->previous=NULL; + delete(present->useful_data); + delete(present); + count--; + } + } + else + { + if (&item==last->useful_data) + { + last=present->previous; + last->next=NULL; + delete(present->useful_data); + delete(present); + count--; + } + else + { + (present->next)->previous=present->previous; + (present->previous)->next=present->next; + delete(present->useful_data); + delete(present); + count--; + } + } + return *this; + } + + // Delete a item of the list without free the useful_data + Rlist<E>& delete_item_1(E& item) + { + int position = get_position(item); + + if (position==-1) return *this; + Rlist_item<E> *present=&(get_at(position)); + + if (&item==first->useful_data) // is the first + { + if (&item==last->useful_data) + { + delete(first); + first=NULL; + last=NULL; + count=0; + } + else + { + first=first->next; + first->previous=NULL; + delete(present); + count--; + } + } + else + { + if (&item==last->useful_data) + { + last=present->previous; + last->next=NULL; + delete(present); + count--; + } + else + { + (present->next)->previous=present->previous; + (present->previous)->next=present->next; + delete(present); + count--; + } + } + return *this; + } + + // Delete item at position "pos" + Rlist<E>& delete_item_by_position(const int pos) + { return delete_item(*(get_at(pos).useful_data)); } + + // Delete the last item in the list + Rlist<E>& delete_last() + { return delete_item(*(last->useful_data)); } + + // delete all items in the list + Rlist<E>& remove() + { + Rlist_item<E> *next,*present=first; + while (present!=NULL) + { + next=present->next; + delete(present->useful_data); + delete(present); + present=next; + } + first=NULL; + last=NULL; + count=0; + return *this; + } + + // Join a new list to this list + Rlist<E>& join(Rlist<E>& new_list) + { + if (new_list.size()==0) + return *this; + + if (first==NULL) + { + first=new_list.get_first(); + last=new_list.get_last(); + } + else + { + last->next=new_list.get_first(); + (new_list.get_first())->previous=last; + last = new_list.get_last(); + } + count += new_list.size(); + new_list.reset(); + return *this; + } + + // Show items of the list + friend ostream& operator<<(ostream& os, const Rlist<E>& list) + { + Rlist_item<E> *present=list.get_first(); + if (list.get_first()==NULL) os << endl << "THE LIST IS EMPTY !!"; + while (present!=NULL) + { + os << endl << (*(present->useful_data)); + // Falta el operador para stat. + // (habra que ver) + present=present->next; + } + return os; + } + + // Copy the list passed + Rlist<E>& operator=(const Rlist<E>& source) + { + E *new_item; + remove(); + if (source.first==NULL && source.last==NULL) + { + first=NULL; + last=NULL; + count=0; + } + else + { + for (int i=0;i<source.size();i++) + { + if ((new_item=(E *)malloc(sizeof(E)))==NULL) + show_message(7); + (*new_item)=*(source.get_at(i).useful_data); + append(*new_item); + } + } + return *this; + } + + // Invert the order of items in the list + Rlist<E>& invert() + { + Rlist_item<E> *present,*interchange; + + present=first; + + for (int i=0;i<size();i++) + { + interchange=present->next; + present->next=present->previous; + present->previous=interchange; + present=interchange; + } + interchange=first; + first=last; + last=interchange; + return (*this); + } +}; // end of class +#endif diff --git a/ProyectoFinal/CHC/malva/src/States.cc b/ProyectoFinal/CHC/malva/src/States.cc new file mode 100644 index 0000000..f36d197 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/States.cc @@ -0,0 +1,228 @@ +/****************************************************************************** + Modified by Carlos Cotta Porras + April 2001 + + Modified by G.J.L.P +******************************************************************************/ + + +#include <string.h> +#include "States.hh" + +// Methods of class State_Vble + + // constructors + State_Vble ::State_Vble () + { + name=NULL; + nitems=0; + length=0; + content=NULL; + } + + State_Vble ::State_Vble (const char *st_name) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + } + + State_Vble::State_Vble (const char *st_name,StateCenter& sc) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + sc.add(*this); + } + + State_Vble ::State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + set_contents(new_contents,new_nitems,new_length); + } + + State_Vble ::State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length,StateCenter& sc) + { + name=strdup(st_name); + nitems=0; + length=0; + content=NULL; + set_contents(new_contents,new_nitems,new_length); + sc.add(*this); + } + + + // Set the name of a state vble. + void State_Vble ::set_name (const char* st_name) // Set the name of a state vble. + { + if (name!=NULL) + free(name); + name=strdup(st_name); + } + + // Get the name of a state vble. + char* State_Vble ::get_name () const // Get the name of a state vble. + { + return name; + } + + // Number of basic items + unsigned long State_Vble ::get_nitems() const // Number of basic items + { + return nitems; + } + + // Get the total number of bytes + unsigned long State_Vble ::get_length () const // Get the total number of bytes + { + return length; + } + + // Fill up a state vble. + void State_Vble ::set_contents (const char *new_contents, unsigned long new_nitems, unsigned long new_length) + { + if (content!=NULL) + free(content); + content=(char *)malloc(new_nitems * new_length); + memcpy(content,new_contents,(new_nitems*new_length)); + nitems=new_nitems; + length=new_length; + } + + // Obtain the contents of a state vble. + void *State_Vble ::get_contents (char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const + { + memcpy(read_contents,content,nitems * length); + read_nitems=nitems; + read_length=length; + return NULL; + } + + ostream& operator<< (ostream& os,const State_Vble& st) + { + os << endl << st.name + << endl << st.nitems + << endl << st.length + << endl << st.content; + + return os; + } + + State_Vble ::~State_Vble () + { + free(content); + free(name); + } + +// Methods of class StateCenter + + StateCenter::StateCenter():state_variables() + {} + + // searchs a state variable + State_Vble *StateCenter::find(const char *st_name) const + { + Rlist_item<State_Vble> *current_state=state_variables.get_first(); + + for (int i=0;i<state_variables.size();i++) + { + if (!(strcmp(current_state->data().get_name(),st_name))) + return &(current_state->data()); + current_state=¤t_state->next_item(); + } + return NULL; + } + + // Add one state variable + void StateCenter::add(State_Vble& st) + { + State_Vble *found_state=find(st.get_name()); + if (found_state==NULL) + state_variables.append(st); + else + cout << endl << "You are trying to introduce a state variable that is yet used in the skeleton !!" << st.get_name(); + } + + void StateCenter::add(State_Vble *st) + { + State_Vble *found_state=find(st->get_name()); + if (found_state==NULL) + state_variables.append(*st); + else + cout << endl << "You are trying to introduce a state variable that is yet used in the skeleton !!" << st->get_name(); + } + + // Remove one state variable + void StateCenter::remove(const char* st_name) + { + State_Vble *found_state=find(st_name); + if (found_state!=NULL) + state_variables.delete_item_1(*found_state); + } + + // Update the contents of one vble. + void StateCenter::update(const char* st_name, const State_Vble& st) const // Update the contents of one vble. + { + State_Vble *found_state=find(st_name); + if (found_state!=NULL) + { + char *a=(char *)malloc(found_state->get_nitems() * found_state->get_length()); + unsigned long nitems,length; + st.get_contents(a,nitems,length); + found_state->set_contents(a,nitems,length); + free(a); + } + } + + // Get a vble. with a given name + State_Vble& StateCenter::get(const char* st_name) const // Get a vble. with a given name + { + State_Vble *found_state=find(st_name); + return *found_state; + } + + // Allows an easy iterated extraction + State_Vble* StateCenter::get_next(const State_Vble& st) const + { + State_Vble *found_state=find(st.get_name()); + if (found_state==NULL) return NULL; + if ( state_variables.get_at(state_variables.get_position(*found_state)).is_last()) return NULL; + else return &(state_variables.get_at(state_variables.get_position(*found_state)).next_item().data()); + } + + // returns the number of state variables + unsigned int StateCenter::size() const + { + return state_variables.size(); + } + + // Obtain the contents of a state vble. of name st_name + void StateCenter::get_contents_state_variable(const char *st_name,char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const + { + get(st_name).get_contents(read_contents,read_nitems,read_length); + } + + // Fill up a state vble.of name st_name + void StateCenter::set_contents_state_variable(const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) const + { + get(st_name).set_contents(new_contents,new_nitems,new_length); + } + + void StateCenter::removeAll() + { + while(state_variables.get_first()) + { + Rlist_item<State_Vble>* v = state_variables.get_first(); + remove(v->useful_data->get_name()); + } + } + + StateCenter::~StateCenter() + { + removeAll(); + } diff --git a/ProyectoFinal/CHC/malva/src/States.hh b/ProyectoFinal/CHC/malva/src/States.hh new file mode 100644 index 0000000..e3a215f --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/States.hh @@ -0,0 +1,64 @@ +/******************************************************************************************************** +*** *** +*** Class StateCenter: Pool of state variables for skeletons *** +*** *** +*** Class State_Vble: State Variable of a skeleton *** +*** *** +*********************************************************************************************************/ + +#ifndef STATE_CENTER +#define STATE_CENTER 1 + +#include "Rlist.h" +#include <iostream> + +class StateCenter; + +class State_Vble +{ + private: + char *name; + unsigned long nitems; + unsigned long length; + char *content; + + public: + // constructors + State_Vble (); + State_Vble (const char *st_name); + State_Vble (const char *st_name,StateCenter& sc); + State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length); + State_Vble (const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length,StateCenter& sc); + + void set_name (const char* st_name); // Set the name of a state vble. + char* get_name () const; // Get the name of a state vble. + unsigned long get_nitems() const; + unsigned long get_length () const; // Get the total number of bytes + void set_contents (const char *new_contents, unsigned long new_nitems, unsigned long new_length); // Fill up a state vble. + void *get_contents (char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const; // Obtain the contents of a state vble. + friend ostream& operator<< (ostream& os,const State_Vble& st); + ~State_Vble (); +}; + +class StateCenter +{ + private: + Rlist<State_Vble> state_variables; + + public: + StateCenter(); + State_Vble *find(const char *st_name) const; // search a state variable + void add(State_Vble& st); // Add one state variable + void add(State_Vble *st); // Add one state variable + void remove(const char* st_name); // Remove one state variable + void removeAll(); // Removes all variables + void update(const char* st_name, const State_Vble& st) const; // Update the contents of one vble. + State_Vble& get(const char* st_name) const; // Get a vble. with a given name + State_Vble* get_next(const State_Vble& st) const; // Allows an easy iterated extraction + unsigned int size() const; // returns the number of state variables + void get_contents_state_variable(const char *st_name,char *read_contents, unsigned long& read_nitems, unsigned long& read_length) const; // Obtain the contents of a state vble. of name st_name + void set_contents_state_variable(const char *st_name,const char *new_contents, unsigned long new_nitems, unsigned long new_length) const; // Fill up a state vble.of name st_name + ~StateCenter(); +}; + +#endif diff --git a/ProyectoFinal/CHC/malva/src/States.o b/ProyectoFinal/CHC/malva/src/States.o new file mode 100644 index 0000000000000000000000000000000000000000..f5e95c8928fb22e26363c12820d0e56fd98709d2 GIT binary patch literal 12968 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 literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/src/mallba.hh b/ProyectoFinal/CHC/malva/src/mallba.hh new file mode 100644 index 0000000..e4a35c0 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/mallba.hh @@ -0,0 +1,26 @@ +/***************************************************************************** +*** *** +*** Este fichero hace algunas declaraciones y declara algunos tipos comu- *** +*** nes a todos los algoritmos implementados. *** +*** *** +*****************************************************************************/ + +#ifndef INC_mallba_hh +#define INC_mallba_hh + +#define skeleton namespace +#define requires +#define provides +#define hybridizes(x) +#define inherits typedef +#define as + +enum Direction { minimize=-1,maximize=1}; + +extern const double plus_infinity; +extern const double minus_infinity; + +#define false 0 +#define true 1 + +#endif diff --git a/ProyectoFinal/CHC/malva/src/netstream.cc b/ProyectoFinal/CHC/malva/src/netstream.cc new file mode 100644 index 0000000..932e89e --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/netstream.cc @@ -0,0 +1,380 @@ +/*************************************************************************** + *** netstream.cc *** + *** v1.6 - July 2001 *** + ** *** + *** v1.5 - March 2001 *** + *** v1.0 - November 2000 *** + *** *** + *** v1.5 extends v1.0: *** + *** .- Changes metods init() and finalize() to be static *** + *** .- Incorporates process group management *** + *** .- Do not consider LEDA anymore *** + *** .- Contains a method "int my_pid()" for easy invokations *** + *** .- Adds "unsigned" and "long double" input/output *** + *** *** + *** v1.6 extends v1.5: *** + ** .- Internal in/out buffers for packed separated *** + *** *** + *** Communication services for LAN/WAN use following the message *** + *** passing paradigm. *** + *** STREAM C++ VERSION *** + *** MPI implementation *** + *** Developed by Erique Alba *** + ***************************************************************************/ +#include "netstream.hh" +// Default constructor +NetStream::NetStream() +{ + this->reset(); // Reset to default values member variables + packin_buffer = new char[MAX_PACK_BUFFER_SIZE]; + packout_buffer = new char[MAX_PACK_BUFFER_SIZE]; +} +// Init the underlying communication library (MPI) +NetStream::NetStream (int argc, char ** argv) +{ + init(argc,argv); + this->reset(); + packin_buffer = new char[MAX_PACK_BUFFER_SIZE]; + packout_buffer = new char[MAX_PACK_BUFFER_SIZE]; +} +// Default destructor +NetStream::~NetStream() +{ + delete [] packin_buffer; delete [] packout_buffer; + this->reset(); +} +// Give default values to member variables +void NetStream::reset(void) +{ + default_target = default_source = 0; + pack_in_progress = false; + packin_index = packout_index = 0; + pending_input_packet = false; + pack_in = pack_out = false; + broadcast = false; + my_communicator = MPI_COMM_WORLD; +} +// Init the communication system. Invoke it only ONCE +void NetStream::init(int argc, char** argv) +{ + static bool system_up = false; // Is MPI already running? + if (!system_up) + { MPI_Init(&argc,&argv); + system_up = true; + } +} +// Shutdown the communication system. Invoke it ONCE +void NetStream::finalize(void) +{ + MPI_Finalize(); // Unconditional Finalization +} +// BASIC INPUT/OUTPUT SERVICES +// =================================================================================== + +NetStream& NetStream::operator>> (bool& d) +{ rcv(&d,1,NET_BOOL,default_source); return(*this); } + +NetStream& NetStream::operator<< (bool d) +{ send(&d,1,NET_BOOL,default_target); return(*this); } +NetStream& NetStream::operator>> (char& d) +{ rcv(&d,1,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (char d) +{ send(&d,1,NET_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (short& d) +{ rcv(&d,1,NET_SHORT,default_source); return(*this); } +NetStream& NetStream::operator<< (short d) +{ send(&d,1,NET_SHORT,default_target); return(*this); } +NetStream& NetStream::operator>> (int& d) +{ rcv(&d,1,NET_INT,default_source); return(*this); } +NetStream& NetStream::operator<< (int d) +{ send(&d,1,NET_INT,default_target); return(*this); } +NetStream& NetStream::operator>> (long& d) +{ rcv(&d,1,NET_LONG,default_source); return(*this); } +NetStream& NetStream::operator<< (long d) +{ send(&d,1,NET_LONG,default_target); return(*this); } +NetStream& NetStream::operator>> (float& d) +{ rcv(&d,1,NET_FLOAT,default_source); return(*this); } +NetStream& NetStream::operator<< (float d) +{ send(&d,1,NET_FLOAT,default_target); return(*this); } +NetStream& NetStream::operator>> (double& d) +{ rcv(&d,1,NET_DOUBLE,default_source); return(*this); } +NetStream& NetStream::operator<< (double d) +{ send(&d,1,NET_DOUBLE,default_target); return(*this); } +NetStream& NetStream::operator>> (char* d) +{ rcv(d,MAX_MSG_LENGTH,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (char* d) +{ send(d,strlen(d)+1,NET_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (void* d) +{ rcv(d,MAX_MSG_LENGTH,NET_CHAR,default_source); return(*this); } +NetStream& NetStream::operator<< (void* d) +{ send(d,strlen((char*)d)+1,NET_CHAR,default_target); return(*this); } +// Extended data types from version 1.5 on +NetStream& NetStream::operator>> (unsigned char& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_CHAR,default_source);return(*this); } + +NetStream& NetStream::operator<< (unsigned char d) +{ send(&d,1,NET_UNSIGNED_CHAR,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned short int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_SHORT,default_source);return(*this); } +NetStream& NetStream::operator<< (unsigned short int d) +{ send(&d,1,NET_UNSIGNED_SHORT,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED,default_source); return(*this); } + +NetStream& NetStream::operator<< (unsigned int d) +{ send(&d,1,NET_UNSIGNED,default_target); return(*this); } +NetStream& NetStream::operator>> (unsigned long int& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_UNSIGNED_LONG,default_source);return(*this); } + +NetStream& NetStream::operator<< (unsigned long int d) +{ send(&d,1,NET_UNSIGNED_LONG,default_target); return(*this); } +NetStream& NetStream::operator>> (long double& d) +{ rcv(&d,MAX_MSG_LENGTH,NET_LONG_DOUBLE,default_source); return(*this); } + +NetStream& NetStream::operator<< (long double d) +{ send(&d,1,NET_LONG_DOUBLE,default_target); return(*this); } +// SET-GET TARGET AND SOURCE PROCESSES +NetStream& __set_target(NetStream& n, const int p) { return n._set_target(p); } +NetStream& NetStream::_set_target(const int p) +{ assert(p>=0); default_target = p; return (*this); } +NetStream& __get_target(NetStream& n, int* p) { return n._get_target(p); } +NetStream& NetStream::_get_target(int* p) +{ *p = default_target; return (*this); } +NetStream& __set_source(NetStream& n, const int p) { return n._set_source(p); } +NetStream& NetStream::_set_source(const int p) +{ /*assert(p>=0);*/ default_source = p; return (*this); } +NetStream& __get_source(NetStream& n, int* p) { return n._get_source(p); } +NetStream& NetStream::_get_source(int* p) +{ *p = default_source; return (*this); } +// Get the number of processes involved in the communications +int NetStream::pnumber(void) +{ int numprocs, rvalue; + rvalue = MPI_Comm_size(my_communicator,&numprocs); + assert(rvalue==MPI_SUCCESS); + return numprocs; +} +// MANIPULATORS: SYNCHRONIZATION AND PACKING SERVICES +// =================================================================================== +// Get the process ID [0, 1, 2, ...] fro the calling process +NetStream& __my_pid(NetStream& n, int* pid) +{ + return n._my_pid(pid); +} +NetStream& NetStream::_my_pid(int* pid) +{ + MPI_Comm_rank(my_communicator,pid); + return (*this); +} +// EASY access to rank - Returns the process ID of the calling process +int NetStream::my_pid(void) +{ int pid; + this->_my_pid(&pid); + return pid; +} +// Sit and wait until all processes are in the same barrier +// Can be used as a MANIPULATOR +NetStream& barrier(NetStream& n) +{ + return n._barrier(); +} +NetStream& NetStream::_barrier(void) +{ int status; + status = MPI_Barrier(my_communicator); + assert(status==MPI_SUCCESS); + return (*this); +} +// Wait for an incoming message in any input stream +NetStream& NetStream::_wait(const int stream_type) // class +{ + int rvalue; + MPI_Status status; + assert(stream_type==regular||stream_type==packed||stream_type==any); + if( ((stream_type==packed) || (stream_type==any) )&& (pending_input_packet) ) + //if( (stream_type==packed) && (pending_input_packet) ) + return (*this); // wait befor packet_begin when already received + rvalue = MPI_Probe(default_source,stream_type,my_communicator,&status); + assert(rvalue==MPI_SUCCESS); + return (*this); +} + +NetStream& NetStream::_wait2(const int stream_type, int& tipo) // class +{ + int rvalue; + MPI_Status status; + assert(stream_type==regular||stream_type==packed||stream_type==any); + if( ((stream_type==packed) || (stream_type==any) )&& (pending_input_packet) ) + //if( (stream_type==packed) && (pending_input_packet) ) + return (*this); // wait befor packet_begin when already received + rvalue = MPI_Probe(default_source,stream_type,my_communicator,&status); + assert(rvalue==MPI_SUCCESS); + if (status.MPI_SOURCE == 0){ + tipo = 1; + } + return (*this); +} +NetStream& __wait(NetStream& n, const int stream_type) // helper +{ + return n._wait(stream_type); +} +// Marks the beginning of a packed information +NetStream& pack_begin(NetStream& n) +{ + return n._pack_begin(); +} +NetStream& NetStream::_pack_begin(void) +{ + int rvalue=MPI_SUCCESS; + MPI_Status status; + if(!pack_in_progress) + { pack_in_progress = true; + packin_index = packout_index = 0; + pack_in = false; + pack_out = false; + if (!pending_input_packet) + { _probe(packed,pending_input_packet); + if(pending_input_packet) + rvalue = MPI_Recv(packin_buffer, MAX_PACK_BUFFER_SIZE, NET_PACKED, + default_source, PACKED_STREAM_TAG, my_communicator, &status); + } + } + return (*this); +} +// Marks the end of a packed and flush it to the net +NetStream& pack_end(NetStream& n) +{ + return n._pack_end(); +} +NetStream& NetStream::_pack_end(void) +{ + int rvalue, mypid; + if (pack_in_progress) + { + if(pack_out) + { if(broadcast) // Packet broadcast + { broadcast = false; + _my_pid(&mypid); + rvalue = MPI_Bcast(packout_buffer,packout_index,NET_PACKED, + mypid,my_communicator); + assert(rvalue==MPI_SUCCESS); + } + else + { rvalue = MPI_Send(packout_buffer, packout_index, NET_PACKED, + default_target,PACKED_STREAM_TAG,my_communicator); + assert(rvalue==MPI_SUCCESS); + } + } + pack_in_progress = false; + pack_in = pack_out = false; + packin_index = packout_index = 0 ; + } + return (*this); +} +// Check whether there are awaiting data +NetStream& probe(NetStream& n, const int stream_type, int& pending) +{ + return n._probe(stream_type, pending); +} +NetStream& NetStream::_probe(const int stream_type, int& pending) +{ + MPI_Status status; + int rvalue; + assert(stream_type==regular||stream_type==packed||stream_type==any); + rvalue = MPI_Iprobe(default_source,stream_type,my_communicator,&pending,&status); + assert(rvalue==MPI_SUCCESS); + return (*this); +} +// Broadcast a message to all the processes +NetStream& broadcast(NetStream& n) +{ + return n._broadcast(); +} +NetStream& NetStream::_broadcast(void) +{ + broadcast = true; + return (*this); +} +// PRIVATE SERVICES +// =================================================================================== +// Usually, the length is the number of bytes for every net type +// When packing we must use in the pack calls the numer of items (length divided by type size) +// Any char is encoded with a leading field of length +void NetStream::send(void* d, const int len, const NET_TYPE type, const int target) +{ + int rvalue = MPI_SUCCESS, length = len; + // PACKING SERVICE + if(pack_in_progress) + { + pack_out = true; + assert(pack_out!=pack_in); // Error condition + if(type==NET_CHAR) + send(&length,sizeof(NET_INT),NET_INT,target); // Recursive call to store string length + else + length = 1; + rvalue = MPI_Pack(d,length,type,packout_buffer,MAX_PACK_BUFFER_SIZE,&packout_index,my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + if(broadcast) // Regular broadcast, packed broadcast managed in _pack_end() + { int mypid; + + broadcast = false; + _my_pid(&mypid); + rvalue = MPI_Bcast(d,len,type,mypid,my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + rvalue = MPI_Send(d,len,type,target,REGULAR_STREAM_TAG,my_communicator); + assert(rvalue==MPI_SUCCESS); +} +void NetStream::rcv (void* d, const int len, const NET_TYPE type, const int source) +{ MPI_Status status; + int rvalue = MPI_SUCCESS, length=len; + if(pack_in_progress) + { +// if(!pack_in && !pending_input_packet) +// rvalue = MPI_Recv(packin_buffer, MAX_PACK_BUFFER_SIZE, NET_PACKED, +// default_source, PACKED_STREAM_TAG, my_communicator, &status); + pack_in = true; + pending_input_packet = false; + assert(pack_out!=pack_in); + if(type==NET_CHAR) + rcv(&length,sizeof(NET_INT),NET_INT,source); // Gets the string length + else + length = 1; + rvalue = MPI_Unpack(packin_buffer, MAX_PACK_BUFFER_SIZE, &packin_index, d, + length, type, my_communicator); + assert(rvalue==MPI_SUCCESS); + return; + } + + rvalue=MPI_Recv(d,len,type,source,REGULAR_STREAM_TAG,my_communicator,&status); + assert(status.MPI_ERROR==MPI_SUCCESS); + assert(rvalue==MPI_SUCCESS); +} +/////////////////////////////////////// GROUP MANAGEMENT //////////////////////////////// +// Set the netstream to a new communicator +void NetStream::set_communicator(NET_Comm comm) +{ + my_communicator = comm; +} +// Get the present communicator in this netstream +NET_Comm NetStream::get_communicator(void) +{ + return my_communicator; +} +// Create a new group inside the present communicator +NET_Comm NetStream::create_group(NET_Comm comm, int color, int key) +{ int rvalue; + NET_Comm newcomm; + rvalue=MPI_Comm_split(comm,color,key,&newcomm); + assert(rvalue==MPI_SUCCESS); + return newcomm; +} +// Create a bridge between local and remote MATCHING call +NET_Comm NetStream::create_inter_group(NET_Comm lcomm, int lrank, NET_Comm bcomm, int rrank, int strtype) +{ int rvalue; + NET_Comm newcomm; + rvalue=MPI_Intercomm_create(lcomm,lrank,bcomm,rrank,strtype,&newcomm); + assert(rvalue==MPI_SUCCESS); + return newcomm; +} diff --git a/ProyectoFinal/CHC/malva/src/netstream.hh b/ProyectoFinal/CHC/malva/src/netstream.hh new file mode 100644 index 0000000..5c24a3d --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/netstream.hh @@ -0,0 +1,161 @@ +/*************************************************************************** + *** netstream.cc *** + *** v1.6 - July 2001 *** + ** *** + *** v1.5 - March 2001 *** + *** v1.0 - November 2000 *** + *** *** + *** v1.5 extends v1.0: *** + *** .- Changes metods init() and finalize() to be static *** + *** .- Incorporates process group management *** + *** .- Do not consider LEDA anymore *** + *** .- Contains a method "int my_pid()" for easy invokations *** + *** .- Adds "unsigned" and "long double" input/output *** + *** *** + *** v1.6 extends v1.5: *** + ** .- Internal in/out buffers for packed separated *** + *** *** + *** Communication services for LAN/WAN use following the message *** + *** passing paradigm. *** + *** STREAM C++ VERSION *** + *** MPI implementation *** + *** Developed by Erique Alba *** + ***************************************************************************/ +#ifndef INC_netstream +#define INC_netstream +#include "mpi.h" +#include <assert.h> +#include <string.h> +// Class NetStream allows to define and use network streams trhough LAN and WAN +#define REGULAR_STREAM_TAG 0 // Used for tagging MPI regular messages +#define PACKED_STREAM_TAG 1 // Used for tagging MPI packet messages +#define NET_TYPE MPI_Datatype // Network allowable data types +#define NET_BOOL MPI_CHAR // Bools like chars +#define NET_CHAR MPI_CHAR +#define NET_SHORT MPI_SHORT +#define NET_INT MPI_INT +#define NET_LONG MPI_LONG +#define NET_UNSIGNED_CHAR MPI_UNSIGNED_CHAR +#define NET_UNSIGNED_SHORT MPI_UNSIGNED_SHORT +#define NET_UNSIGNED MPI_UNSIGNED +#define NET_UNSIGNED_LONG MPI_UNSIGNED_LONG +#define NET_FLOAT MPI_FLOAT +#define NET_DOUBLE MPI_DOUBLE +#define NET_LONG_DOUBLE MPI_LONG_DOUBLE +#define NET_BYTE MPI_BYTE +#define NET_PACKED MPI_PACKED +#define NET_Comm MPI_Comm +#define MAX_MSG_LENGTH 204800 // Max length of a message +#define MAX_PACK_BUFFER_SIZE 204800 // Max length of a packed message +// Help structure for manipulators having one int& argument +class NetStream; +struct smanip1c // "const int" +{ NetStream& (*f)(NetStream&, const int); // The ONE argument function + int i; // The argument + smanip1c( NetStream&(*ff)(NetStream&,const int), int ii) : f(ff), i(ii) {} // Constuctor +}; +struct smanip1 // "int*" note: references do not work! "int&" +{ NetStream& (*f)(NetStream&, int*); // The ONE argument function + int* i; // The argument + smanip1( NetStream&(*ff)(NetStream&, int*), int* ii) : f(ff), i(ii) {} // Constuctor +}; +// Tags for the available streams +const int any = MPI_ANY_TAG; // Tag value valid for any stream +const int regular = REGULAR_STREAM_TAG; // Tag value for regular stream of data +const int packed = PACKED_STREAM_TAG; // Tag value for packed stream of data +// Tags for sources +const int any_source = MPI_ANY_SOURCE; // Tag value valid for any source +class NetStream +{ + public: + NetStream (); // Default constructor + // Constructor with source integer left unchanged + NetStream (int, char **); // Init the communications + ~NetStream (); // Default destructor + static void init(int,char**); // Init the communication system. Invoke it only ONCE + static void finalize(void); // Shutdown the communication system. Invoke it ONCE + // GROUP management + void set_communicator(NET_Comm comm); // Set the netstream to a new communicator + NET_Comm get_communicator(void); // Get the present communicator in this netstream + static NET_Comm create_group(NET_Comm comm, int color, int key); // Create a new group inside the present communicator + // Create a bridge between local and remote MATCHING call + static NET_Comm create_inter_group(NET_Comm lcomm, int lrank, NET_Comm bcomm, int rrank, int strtrype); + +// BASIC INPUT SERVICES <comments> BASIC OUTPUT SERVICES +// ============================================================================================================ + NetStream& operator>> (bool& d); NetStream& operator<< (bool d); + NetStream& operator>> (char& d); NetStream& operator<< (char d); + NetStream& operator>> (short& d); NetStream& operator<< (short d); + NetStream& operator>> (int& d); NetStream& operator<< (int d); + NetStream& operator>> (long& d); NetStream& operator<< (long d); + NetStream& operator>> (float& d); NetStream& operator<< (float d); + NetStream& operator>> (double& d); NetStream& operator<< (double d); + NetStream& operator>> (char* d); /*NULL terminated*/ NetStream& operator<< (char* d); + NetStream& operator>> (void* d); /*NULL terminated*/ NetStream& operator<< (void* d); + // Extended data types from version 1.5 on + NetStream& operator>> (unsigned char& d); NetStream& operator<< (unsigned char d); + NetStream& operator>> (unsigned short int& d); NetStream& operator<< (unsigned short int d); + NetStream& operator>> (unsigned int& d); NetStream& operator<< (unsigned int d); + NetStream& operator>> (unsigned long int& d); NetStream& operator<< (unsigned long int d); + NetStream& operator>> (long double& d); NetStream& operator<< (long double d); + int pnumber(void); // Returns the number of processes + bool broadcast; // Determines whether the next sent message is for broadcasting + // Input MANIPULATORS for modifying the behavior of the channel on the fly + // NO ARGUMENTS + NetStream& operator<< (NetStream& (*f)(NetStream& n)) { return f(*this); } // NO arguments + NetStream& _barrier(void); // Sit and wait until all processes are in barrier + NetStream& _pack_begin(void); // Marks the beginning of a packed information + NetStream& _pack_end(void); // Marks the end of a packed and flush it to the net + NetStream& _probe(const int stream_type, int& pending); // Check whether there are awaiting data + NetStream& _broadcast(void); // Broadcast a message to all the processes + // ONE ARGUMENT + // "const int" + NetStream& operator<< (smanip1c m) { return m.f((*this),m.i); }// ONE int& argument constant + // "int*" + NetStream& operator<< (smanip1 m) { return m.f((*this),m.i); }// ONE int& argument + // BASIC CLASS METHODS FOR MANIPULATORS + NetStream& _my_pid(int* pid); // Returns the process ID of the calling process + NetStream& _wait(const int stream_type); // Wait for an incoming message in the specified stream + NetStream& _wait2(const int stream_type, int& tipo); + NetStream& _set_target(const int p); // Stablish "p" as the default receiver + NetStream& _get_target(int* p); // Get into "p" the default receiver + NetStream& _set_source(const int p); // Stablish "p" as the default transmitter + NetStream& _get_source(int* p); // Get into "p" the default transmitter + // AUXILIAR PUBLIC METHODS FOR ALLOWING EASY MANAGEMENTS OF NETSTREAMS + int my_pid(void); // Returns the process ID of the calling process + private: + int default_target, default_source; // Default process IDs to send-recv data to-from + bool pack_in_progress; // Defines whether a packet is being defined with "pack_begin-pack_end" + int packin_index; // Index to be used for extracting from a IN packed message - v1.6 + int packout_index; // Index to be used for adding to an OUT packed message - v1.6 + int pending_input_packet;//Is there a pending packet already read into the IN buffer? - v1.6 + char* packin_buffer; // Buffer to temporary storage of the IN packed being defined - v1.6 + char* packout_buffer; // Buffer to temporary storage of the OUT packed being defined - v1.6 + bool pack_in, pack_out; // Define whether input-output packed message is being used + void reset(void); // Reset member variables of this class + NET_Comm my_communicator; // Communicator of this netstream + void send(void* d, const int len, const NET_TYPE type, const int target); + void rcv (void* d, const int len, const NET_TYPE type, const int source); +}; // class NetStream + // MANIPULATORS (must be static or non-member methods in C++ -mpiCC only allows non-member!-) + // NO ARGUMENTS + NetStream& barrier(NetStream& n); // Sit and wait until all processes are in barrier + NetStream& broadcast(NetStream& n); // Broadcast a message to all the processes + NetStream& pack_begin(NetStream& n); // Marks the beginning of a packed information + NetStream& pack_end(NetStream& n); // Marks the end of a packed and flush it to the net + // ONE ARGUMENT + NetStream& __my_pid(NetStream& n, int* pid); // Returns the process ID of the calling process + inline smanip1 my_pid(int* pid){ return smanip1(__my_pid,pid); } // manipulator + NetStream& __wait(NetStream& n, const int stream_type);// Wait for an incoming message - helper + inline smanip1c wait(const int stream_type){ return smanip1c(__wait,stream_type); } // manipulator + NetStream& __set_target(NetStream& n, const int p); // Stablish "p" as the default receiver + inline smanip1c set_target(const int p){ return smanip1c(__set_target,p); } // manipulator + NetStream& __get_target(NetStream& n, int* p); // Get into "p" the default receiver + inline smanip1 get_target(int* p){ return smanip1(__get_target,p); } // manipulator + NetStream& __set_source(NetStream& n, const int p); // Stablish "p" as the default transmitter + inline smanip1c set_source(const int p){ return smanip1c(__set_source,p); } // manipulator + NetStream& __get_source(NetStream& n, int* p); // Get into "p" the default transmitter + inline smanip1 get_source(int* p){ return smanip1(__get_source,p); } // manipulator + // TWO ARGUMENTS - not used yet + NetStream& probe(NetStream& n, const int stream_type, int& pending); // Check whether there are awaiting data +#endif diff --git a/ProyectoFinal/CHC/malva/src/netstream.o b/ProyectoFinal/CHC/malva/src/netstream.o new file mode 100644 index 0000000000000000000000000000000000000000..fb40ece360fb739d83d40beffbf1b01c031a15aa GIT binary patch literal 18752 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 WPq&ZTAtmkCLk1+?U$LKx<M;m{=Bs=F literal 0 HcmV?d00001 diff --git a/ProyectoFinal/CHC/malva/src/random.hh b/ProyectoFinal/CHC/malva/src/random.hh new file mode 100644 index 0000000..ae6bde6 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/random.hh @@ -0,0 +1,50 @@ +/****************************************************************************** +*** *** +*** Este fichero contiene funciones (en general inlines) para generar núme- *** +*** ros aleatorios y otras funciones relacionadas con ello *** +*** *** +*******************************************************************************/ + +#ifndef INC_random_hh +#define INC_random_hh + +#include <stdlib.h> + + +inline double undefined () +{ + double zero = 0; + return zero/zero; +} + +// Returns a valeu greater than any other +inline double infinity () +{ + double one=1.0; + double zero=0.0; + return one/zero; +} + +// Returns a random number in [0,1]. +inline double rand01 () +{ + return drand48(); +} + +// Returns a random number +inline int rand_int (float min,float max) +{ + int value=rand(); + int range= (int)(max - min); + int order = value % (range+1); + return ((int)min + order); +} + +// selects a seed +inline void random_seed(long int seed) +{ + srand48(seed); + srand(seed); +} + +#endif diff --git a/ProyectoFinal/CHC/malva/src/time.hh b/ProyectoFinal/CHC/malva/src/time.hh new file mode 100644 index 0000000..088f4d5 --- /dev/null +++ b/ProyectoFinal/CHC/malva/src/time.hh @@ -0,0 +1,43 @@ +/****************************************************************************** +*** *** +*** Este fichero incluye algunas funciones útiles para la medicion de tiem- *** +*** pos. *** +*** *** +******************************************************************************/ + +#ifndef INC_time_hh +#define INC_time_hh + +#define MAXTIME 4294 + +#include <time.h> +#include <sys/time.h> +#include <unistd.h> + +// return time in microseconds +inline float _used_time() +{ + struct timeval tv ; + static long tiempo = -1; + float u_clock; + + gettimeofday(&tv,NULL); + + if(tiempo < 0) tiempo = tv.tv_sec; + + u_clock = ((float)(tv.tv_sec - tiempo)*1000000.0) + ((float)tv.tv_usec); + return u_clock; + +} + + +inline float _used_time(float time) +{ + float dif=_used_time() - time; + if (dif<0) dif = 0; + return dif; +} + + + +#endif diff --git a/ProyectoFinal/CHC/malva/stat/file_stat_aco b/ProyectoFinal/CHC/malva/stat/file_stat_aco new file mode 100644 index 0000000..8426ce4 --- /dev/null +++ b/ProyectoFinal/CHC/malva/stat/file_stat_aco @@ -0,0 +1,12 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/CHC/malva/stat/file_stat_pop b/ProyectoFinal/CHC/malva/stat/file_stat_pop new file mode 100644 index 0000000..8512575 --- /dev/null +++ b/ProyectoFinal/CHC/malva/stat/file_stat_pop @@ -0,0 +1,13 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.eval +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/CHC/malva/stat/file_stat_pso b/ProyectoFinal/CHC/malva/stat/file_stat_pso new file mode 100644 index 0000000..672f857 --- /dev/null +++ b/ProyectoFinal/CHC/malva/stat/file_stat_pso @@ -0,0 +1,12 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.worse_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $4}' > $1.iter +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/CHC/malva/stat/file_stat_sa b/ProyectoFinal/CHC/malva/stat/file_stat_sa new file mode 100644 index 0000000..d006462 --- /dev/null +++ b/ProyectoFinal/CHC/malva/stat/file_stat_sa @@ -0,0 +1,13 @@ +#!/bin/bash + +lines=`cat $1 | wc -l` +head_op=$(($lines - 1)) +tail_op=$(($head_op - 5)) + +head -n $head_op $1 | tail -n $tail_op | gawk '{print $2}' > $1.best_fit +head -n $head_op $1 | tail -n $tail_op | gawk '{print $3}' > $1.eval +head -n $head_op $1 | tail -n $tail_op | gawk '{print $4}' > $1.init_temp +head -n $head_op $1 | tail -n $tail_op | gawk '{print $5}' > $1.best_temp +head -n $head_op $1 | tail -n $tail_op | gawk '{print $6}' > $1.time +head -n $head_op $1 | tail -n $tail_op | gawk '{print $7}' > $1.total_time +echo $tail_op > $1.num_exec diff --git a/ProyectoFinal/CHC/malva/uml-comun.gif b/ProyectoFinal/CHC/malva/uml-comun.gif new file mode 100644 index 0000000000000000000000000000000000000000..e86a0eb3c9795f45438a28d1e81e8e0b6ec2b90b GIT binary patch literal 13660 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 literal 0 HcmV?d00001 -- GitLab