From 3180bbb79cbc043d0ad15293cf9e5b960de80d4d Mon Sep 17 00:00:00 2001 From: Gonzalo Menendez Berch - ENS <gonzalo.menendez@pcunix136.fing.edu.uy> Date: Wed, 5 Sep 2018 21:19:31 -0300 Subject: [PATCH] lmao --- malva/.Rhistory | 0 malva/.cproject | 134 + malva/.gitignore | 6 + malva/.project | 79 + 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 + malva/README.md | 278 + malva/environment | 20 + malva/inc/Mallba | 1 + malva/inc/inc.env | 1 + malva/lib/Makefile | 8 + malva/lib/libmallba.a | Bin 0 -> 34998 bytes malva/rep/CHC/CHC.cfg | 15 + malva/rep/CHC/CHC.hh | 909 +++ malva/rep/CHC/CHC.pro.cc | 3033 ++++++++ malva/rep/CHC/CHC.pro.o | Bin 0 -> 191488 bytes malva/rep/CHC/CHC.req.cc | 332 + malva/rep/CHC/CHC.req.o | Bin 0 -> 25240 bytes malva/rep/CHC/CHCstructures.hh | 29 + malva/rep/CHC/Config.cfg | 3 + malva/rep/CHC/MainLan | Bin 0 -> 150656 bytes malva/rep/CHC/MainLan.cc | 49 + malva/rep/CHC/MainLan.o | Bin 0 -> 8992 bytes malva/rep/CHC/MainSeq | Bin 0 -> 150704 bytes malva/rep/CHC/MainSeq.cc | 43 + malva/rep/CHC/MainSeq.o | Bin 0 -> 8624 bytes malva/rep/CHC/MainWan.cc | 52 + malva/rep/CHC/Makefile | 24 + malva/rep/CHC/res/empty.txt | 0 malva/rep/GA/Config.cfg | 3 + malva/rep/GA/MainLan | Bin 0 -> 148776 bytes malva/rep/GA/MainLan.cc | 53 + malva/rep/GA/MainLan.o | Bin 0 -> 9192 bytes malva/rep/GA/MainSeq | Bin 0 -> 148880 bytes malva/rep/GA/MainSeq.cc | 41 + malva/rep/GA/MainSeq.o | Bin 0 -> 8632 bytes malva/rep/GA/Makefile | 24 + malva/rep/GA/newGA.cfg | 18 + malva/rep/GA/newGA.hh | 855 +++ malva/rep/GA/newGA.pro.cc | 2831 ++++++++ malva/rep/GA/newGA.pro.o | Bin 0 -> 176256 bytes malva/rep/GA/newGA.req.cc | 412 ++ malva/rep/GA/newGA.req.o | Bin 0 -> 36184 bytes malva/rep/GA/newGAstructures.hh | 53 + malva/rep/GA/res/empty.txt | 0 malva/rep/Makefile | 6 + malva/rep/SA/Config.cfg | 3 + malva/rep/SA/MainLan.cc | 53 + malva/rep/SA/MainSeq.cc | 42 + malva/rep/SA/MainWan.cc | 53 + malva/rep/SA/Makefile | 22 + malva/rep/SA/SA.cfg | 9 + malva/rep/SA/SA.hh | 478 ++ 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 + malva/rep/SA/pgfileLan | 1 + 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 + malva/rep/SA/rnd/SA.cfg | 9 + 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 + malva/rep/SA/vrp/SA.cfg | 9 + 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 + malva/src/Makefile | 14 + malva/src/Matrix.hh | 337 + malva/src/Messages.h | 112 + malva/src/Rarray.h | 145 + malva/src/Rlist.h | 415 ++ malva/src/States.cc | 228 + malva/src/States.hh | 64 + malva/src/States.o | Bin 0 -> 12968 bytes malva/src/mallba.hh | 26 + malva/src/netstream.cc | 380 + malva/src/netstream.hh | 161 + malva/src/netstream.o | Bin 0 -> 18752 bytes malva/src/random.hh | 50 + malva/src/time.hh | 43 + malva/stat/file_stat_aco | 12 + malva/stat/file_stat_pop | 13 + malva/stat/file_stat_pso | 12 + malva/stat/file_stat_sa | 13 + malva/uml-comun.gif | Bin 0 -> 13660 bytes 188 files changed, 50755 insertions(+) create mode 100644 malva/.Rhistory create mode 100644 malva/.cproject create mode 100644 malva/.gitignore create mode 100644 malva/.project create mode 100644 malva/Makefile create mode 100644 malva/ProblemInstances/ATSP-instances/br17.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/ft53.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/ft70.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/ftv170.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/ftv70.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/rbg323.atsp create mode 100644 malva/ProblemInstances/ATSP-instances/ry48p.atsp create mode 100644 malva/ProblemInstances/DNAFA-instances/pbm.txt create mode 100644 malva/ProblemInstances/DNAFA-instances/score.txt create mode 100644 malva/ProblemInstances/DNAFA-instances/x60189_4.dat create mode 100644 malva/ProblemInstances/MAXSAT-instances/format.txt create mode 100644 malva/ProblemInstances/MAXSAT-instances/sat1.txt create mode 100644 malva/ProblemInstances/MAXSAT-instances/sat2.txt create mode 100644 malva/ProblemInstances/MTTP-instances/mttp100.dat create mode 100644 malva/ProblemInstances/MTTP-instances/mttp20.dat create mode 100644 malva/ProblemInstances/ONEMAX-instances/format.txt create mode 100644 malva/ProblemInstances/ONEMAX-instances/onemax10.txt create mode 100644 malva/ProblemInstances/RAS-instances/RAS10.txt create mode 100644 malva/ProblemInstances/RAS-instances/RAS20.txt create mode 100644 malva/ProblemInstances/RAS-instances/format.txt create mode 100644 malva/ProblemInstances/RND-instances/rnd149.txt create mode 100644 malva/ProblemInstances/SPHERE-instances/SPH10.txt create mode 100644 malva/ProblemInstances/SPHERE-instances/SPH20.txt create mode 100644 malva/ProblemInstances/SPHERE-instances/format.txt create mode 100644 malva/ProblemInstances/VRP-instances/format.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpinfo.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc1.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc10.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc11.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc12.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc13.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc14.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc2.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc3.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc4.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc5.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc6.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc7.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc8.txt create mode 100644 malva/ProblemInstances/VRP-instances/vrpnc9.txt create mode 100644 malva/README.md create mode 100644 malva/environment create mode 120000 malva/inc/Mallba create mode 100755 malva/inc/inc.env create mode 100644 malva/lib/Makefile create mode 100644 malva/lib/libmallba.a create mode 100644 malva/rep/CHC/CHC.cfg create mode 100644 malva/rep/CHC/CHC.hh create mode 100644 malva/rep/CHC/CHC.pro.cc create mode 100644 malva/rep/CHC/CHC.pro.o create mode 100644 malva/rep/CHC/CHC.req.cc create mode 100644 malva/rep/CHC/CHC.req.o create mode 100644 malva/rep/CHC/CHCstructures.hh create mode 100644 malva/rep/CHC/Config.cfg create mode 100755 malva/rep/CHC/MainLan create mode 100644 malva/rep/CHC/MainLan.cc create mode 100644 malva/rep/CHC/MainLan.o create mode 100755 malva/rep/CHC/MainSeq create mode 100644 malva/rep/CHC/MainSeq.cc create mode 100644 malva/rep/CHC/MainSeq.o create mode 100644 malva/rep/CHC/MainWan.cc create mode 100644 malva/rep/CHC/Makefile create mode 100644 malva/rep/CHC/res/empty.txt create mode 100644 malva/rep/GA/Config.cfg create mode 100755 malva/rep/GA/MainLan create mode 100644 malva/rep/GA/MainLan.cc create mode 100644 malva/rep/GA/MainLan.o create mode 100755 malva/rep/GA/MainSeq create mode 100644 malva/rep/GA/MainSeq.cc create mode 100644 malva/rep/GA/MainSeq.o create mode 100644 malva/rep/GA/Makefile create mode 100644 malva/rep/GA/newGA.cfg create mode 100644 malva/rep/GA/newGA.hh create mode 100644 malva/rep/GA/newGA.pro.cc create mode 100644 malva/rep/GA/newGA.pro.o create mode 100644 malva/rep/GA/newGA.req.cc create mode 100644 malva/rep/GA/newGA.req.o create mode 100644 malva/rep/GA/newGAstructures.hh create mode 100644 malva/rep/GA/res/empty.txt create mode 100644 malva/rep/Makefile create mode 100644 malva/rep/SA/Config.cfg create mode 100644 malva/rep/SA/MainLan.cc create mode 100644 malva/rep/SA/MainSeq.cc create mode 100644 malva/rep/SA/MainWan.cc create mode 100644 malva/rep/SA/Makefile create mode 100644 malva/rep/SA/SA.cfg create mode 100644 malva/rep/SA/SA.hh create mode 100644 malva/rep/SA/SA.req.cc create mode 100644 malva/rep/SA/StopCondition.cc create mode 100644 malva/rep/SA/StopCondition.hh create mode 100644 malva/rep/SA/dnafa/AdjKeys.cpp create mode 100644 malva/rep/SA/dnafa/AdjKeys.h create mode 100644 malva/rep/SA/dnafa/AlignedPair.h create mode 100644 malva/rep/SA/dnafa/Config.cfg create mode 100644 malva/rep/SA/dnafa/ConsensusBuilder.cpp create mode 100644 malva/rep/SA/dnafa/ConsensusBuilder.h create mode 100644 malva/rep/SA/dnafa/ContigBuilder.cpp create mode 100644 malva/rep/SA/dnafa/ContigBuilder.h create mode 100644 malva/rep/SA/dnafa/LayoutBuilder.cpp create mode 100644 malva/rep/SA/dnafa/LayoutBuilder.h create mode 100644 malva/rep/SA/dnafa/MainLan.cc create mode 100644 malva/rep/SA/dnafa/MainSeq.cc create mode 100644 malva/rep/SA/dnafa/Makefile create mode 100644 malva/rep/SA/dnafa/OverlapDetector.cpp create mode 100644 malva/rep/SA/dnafa/OverlapDetector.h create mode 100644 malva/rep/SA/dnafa/SA.cfg create mode 100644 malva/rep/SA/dnafa/SA.hh create mode 100644 malva/rep/SA/dnafa/SA.pro.cc create mode 100644 malva/rep/SA/dnafa/SA.pro.cc1 create mode 100644 malva/rep/SA/dnafa/SA.req.cc create mode 100644 malva/rep/SA/dnafa/StopCondition.cc create mode 100644 malva/rep/SA/dnafa/StopCondition.hh create mode 100644 malva/rep/SA/dnafa/Util.h create mode 100644 malva/rep/SA/dnafa/list.h create mode 100644 malva/rep/SA/dnafa/pgfileLan create mode 100644 malva/rep/SA/dnafa/scp.h create mode 100644 malva/rep/SA/dnafa/sga.cpp create mode 100644 malva/rep/SA/dnafa/sga.h create mode 100644 malva/rep/SA/maxsat/Config.cfg create mode 100644 malva/rep/SA/maxsat/MainLan.cc create mode 100644 malva/rep/SA/maxsat/MainSeq.cc create mode 100644 malva/rep/SA/maxsat/Makefile create mode 100644 malva/rep/SA/maxsat/SA.cfg create mode 100644 malva/rep/SA/maxsat/SA.hh create mode 100644 malva/rep/SA/maxsat/SA.pro.cc create mode 100644 malva/rep/SA/maxsat/SA.req.cc create mode 100644 malva/rep/SA/maxsat/StopCondition.cc create mode 100644 malva/rep/SA/maxsat/StopCondition.hh create mode 100644 malva/rep/SA/maxsat/pgfileLan create mode 100644 malva/rep/SA/onemax/Config.cfg create mode 100644 malva/rep/SA/onemax/MainLan.cc create mode 100644 malva/rep/SA/onemax/MainSeq.cc create mode 100644 malva/rep/SA/onemax/Makefile create mode 100644 malva/rep/SA/onemax/SA.cfg create mode 100644 malva/rep/SA/onemax/SA.hh create mode 100644 malva/rep/SA/onemax/SA.pro.cc create mode 100644 malva/rep/SA/onemax/SA.req.cc create mode 100644 malva/rep/SA/onemax/StopCondition.cc create mode 100644 malva/rep/SA/onemax/StopCondition.hh create mode 100644 malva/rep/SA/onemax/pgfileLan create mode 100644 malva/rep/SA/pgfileLan create mode 100644 malva/rep/SA/pgfileWan create mode 100644 malva/rep/SA/rnd/Config.cfg create mode 100644 malva/rep/SA/rnd/MainLan.cc create mode 100644 malva/rep/SA/rnd/MainSeq.cc create mode 100644 malva/rep/SA/rnd/Makefile create mode 100644 malva/rep/SA/rnd/SA.cfg create mode 100644 malva/rep/SA/rnd/SA.hh create mode 100644 malva/rep/SA/rnd/SA.pro.cc create mode 100644 malva/rep/SA/rnd/SA.req.cc create mode 100644 malva/rep/SA/rnd/StopCondition.cc create mode 100644 malva/rep/SA/rnd/StopCondition.hh create mode 100644 malva/rep/SA/rnd/pgfileLan create mode 100644 malva/rep/SA/vrp/Config.cfg create mode 100644 malva/rep/SA/vrp/MainLan.cc create mode 100644 malva/rep/SA/vrp/MainSeq.cc create mode 100644 malva/rep/SA/vrp/Makefile create mode 100644 malva/rep/SA/vrp/SA.cfg create mode 100644 malva/rep/SA/vrp/SA.hh create mode 100644 malva/rep/SA/vrp/SA.pro.cc create mode 100644 malva/rep/SA/vrp/SA.req.cc create mode 100644 malva/rep/SA/vrp/StopCondition.cc create mode 100644 malva/rep/SA/vrp/StopCondition.hh create mode 100644 malva/rep/SA/vrp/pgfileLan create mode 100644 malva/src/Makefile create mode 100644 malva/src/Matrix.hh create mode 100644 malva/src/Messages.h create mode 100644 malva/src/Rarray.h create mode 100644 malva/src/Rlist.h create mode 100644 malva/src/States.cc create mode 100644 malva/src/States.hh create mode 100644 malva/src/States.o create mode 100644 malva/src/mallba.hh create mode 100644 malva/src/netstream.cc create mode 100644 malva/src/netstream.hh create mode 100644 malva/src/netstream.o create mode 100644 malva/src/random.hh create mode 100644 malva/src/time.hh create mode 100755 malva/stat/file_stat_aco create mode 100755 malva/stat/file_stat_pop create mode 100755 malva/stat/file_stat_pso create mode 100755 malva/stat/file_stat_sa create mode 100644 malva/uml-comun.gif diff --git a/malva/.Rhistory b/malva/.Rhistory new file mode 100644 index 0000000..e69de29 diff --git a/malva/.cproject b/malva/.cproject new file mode 100644 index 0000000..4d31d90 --- /dev/null +++ b/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/malva/.gitignore b/malva/.gitignore new file mode 100644 index 0000000..42fcba1 --- /dev/null +++ b/malva/.gitignore @@ -0,0 +1,6 @@ +.cproject/ +.project/ +.svn/ +.idea/ +.DS_Store + diff --git a/malva/.project b/malva/.project new file mode 100644 index 0000000..1bb914c --- /dev/null +++ b/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/malva/Makefile b/malva/Makefile new file mode 100644 index 0000000..a662e76 --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/br17.atsp b/malva/ProblemInstances/ATSP-instances/br17.atsp new file mode 100644 index 0000000..37313b1 --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/ft53.atsp b/malva/ProblemInstances/ATSP-instances/ft53.atsp new file mode 100644 index 0000000..3f81c5b --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/ft70.atsp b/malva/ProblemInstances/ATSP-instances/ft70.atsp new file mode 100644 index 0000000..75cacb6 --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/ftv170.atsp b/malva/ProblemInstances/ATSP-instances/ftv170.atsp new file mode 100644 index 0000000..22a978b --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/ftv70.atsp b/malva/ProblemInstances/ATSP-instances/ftv70.atsp new file mode 100644 index 0000000..a966e49 --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/rbg323.atsp b/malva/ProblemInstances/ATSP-instances/rbg323.atsp new file mode 100644 index 0000000..c19aa72 --- /dev/null +++ b/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/malva/ProblemInstances/ATSP-instances/ry48p.atsp b/malva/ProblemInstances/ATSP-instances/ry48p.atsp new file mode 100644 index 0000000..b02a98c --- /dev/null +++ b/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/malva/ProblemInstances/DNAFA-instances/pbm.txt b/malva/ProblemInstances/DNAFA-instances/pbm.txt new file mode 100644 index 0000000..38c5037 --- /dev/null +++ b/malva/ProblemInstances/DNAFA-instances/pbm.txt @@ -0,0 +1,2 @@ +30 +/Mallba/ProblemInstances/DNAFA-instances/x60189_4.dat diff --git a/malva/ProblemInstances/DNAFA-instances/score.txt b/malva/ProblemInstances/DNAFA-instances/score.txt new file mode 100644 index 0000000..ff26d92 --- /dev/null +++ b/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/malva/ProblemInstances/DNAFA-instances/x60189_4.dat b/malva/ProblemInstances/DNAFA-instances/x60189_4.dat new file mode 100644 index 0000000..2420540 --- /dev/null +++ b/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/malva/ProblemInstances/MAXSAT-instances/format.txt b/malva/ProblemInstances/MAXSAT-instances/format.txt new file mode 100644 index 0000000..dc630e1 --- /dev/null +++ b/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/malva/ProblemInstances/MAXSAT-instances/sat1.txt b/malva/ProblemInstances/MAXSAT-instances/sat1.txt new file mode 100644 index 0000000..f8aa7fe --- /dev/null +++ b/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/malva/ProblemInstances/MAXSAT-instances/sat2.txt b/malva/ProblemInstances/MAXSAT-instances/sat2.txt new file mode 100644 index 0000000..806241f --- /dev/null +++ b/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/malva/ProblemInstances/MTTP-instances/mttp100.dat b/malva/ProblemInstances/MTTP-instances/mttp100.dat new file mode 100644 index 0000000..9d358cf --- /dev/null +++ b/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/malva/ProblemInstances/MTTP-instances/mttp20.dat b/malva/ProblemInstances/MTTP-instances/mttp20.dat new file mode 100644 index 0000000..9dde3f3 --- /dev/null +++ b/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/malva/ProblemInstances/ONEMAX-instances/format.txt b/malva/ProblemInstances/ONEMAX-instances/format.txt new file mode 100644 index 0000000..179a679 --- /dev/null +++ b/malva/ProblemInstances/ONEMAX-instances/format.txt @@ -0,0 +1 @@ +// dimension of the bitstring. diff --git a/malva/ProblemInstances/ONEMAX-instances/onemax10.txt b/malva/ProblemInstances/ONEMAX-instances/onemax10.txt new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/malva/ProblemInstances/ONEMAX-instances/onemax10.txt @@ -0,0 +1 @@ +10 diff --git a/malva/ProblemInstances/RAS-instances/RAS10.txt b/malva/ProblemInstances/RAS-instances/RAS10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/malva/ProblemInstances/RAS-instances/RAS10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/malva/ProblemInstances/RAS-instances/RAS20.txt b/malva/ProblemInstances/RAS-instances/RAS20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/malva/ProblemInstances/RAS-instances/RAS20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/malva/ProblemInstances/RAS-instances/format.txt b/malva/ProblemInstances/RAS-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/malva/ProblemInstances/RAS-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/malva/ProblemInstances/RND-instances/rnd149.txt b/malva/ProblemInstances/RND-instances/rnd149.txt new file mode 100644 index 0000000..15c44e9 --- /dev/null +++ b/malva/ProblemInstances/RND-instances/rnd149.txt @@ -0,0 +1 @@ +149 diff --git a/malva/ProblemInstances/SPHERE-instances/SPH10.txt b/malva/ProblemInstances/SPHERE-instances/SPH10.txt new file mode 100644 index 0000000..46fc036 --- /dev/null +++ b/malva/ProblemInstances/SPHERE-instances/SPH10.txt @@ -0,0 +1,2 @@ +10 +-5.12 5.12 diff --git a/malva/ProblemInstances/SPHERE-instances/SPH20.txt b/malva/ProblemInstances/SPHERE-instances/SPH20.txt new file mode 100644 index 0000000..1b596f1 --- /dev/null +++ b/malva/ProblemInstances/SPHERE-instances/SPH20.txt @@ -0,0 +1,2 @@ +20 +-5.12 5.12 diff --git a/malva/ProblemInstances/SPHERE-instances/format.txt b/malva/ProblemInstances/SPHERE-instances/format.txt new file mode 100644 index 0000000..5be6f83 --- /dev/null +++ b/malva/ProblemInstances/SPHERE-instances/format.txt @@ -0,0 +1,2 @@ +// number of variables +// range of the variables diff --git a/malva/ProblemInstances/VRP-instances/format.txt b/malva/ProblemInstances/VRP-instances/format.txt new file mode 100644 index 0000000..abccebe --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpinfo.txt b/malva/ProblemInstances/VRP-instances/vrpinfo.txt new file mode 100644 index 0000000..a63a622 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc1.txt b/malva/ProblemInstances/VRP-instances/vrpnc1.txt new file mode 100644 index 0000000..fb9bd54 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc10.txt b/malva/ProblemInstances/VRP-instances/vrpnc10.txt new file mode 100644 index 0000000..bd6fc1b --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc11.txt b/malva/ProblemInstances/VRP-instances/vrpnc11.txt new file mode 100644 index 0000000..adea50e --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc12.txt b/malva/ProblemInstances/VRP-instances/vrpnc12.txt new file mode 100644 index 0000000..939f5dd --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc13.txt b/malva/ProblemInstances/VRP-instances/vrpnc13.txt new file mode 100644 index 0000000..975ff61 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc14.txt b/malva/ProblemInstances/VRP-instances/vrpnc14.txt new file mode 100644 index 0000000..02946d9 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc2.txt b/malva/ProblemInstances/VRP-instances/vrpnc2.txt new file mode 100644 index 0000000..214012a --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc3.txt b/malva/ProblemInstances/VRP-instances/vrpnc3.txt new file mode 100644 index 0000000..8bfcc47 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc4.txt b/malva/ProblemInstances/VRP-instances/vrpnc4.txt new file mode 100644 index 0000000..3faf64a --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc5.txt b/malva/ProblemInstances/VRP-instances/vrpnc5.txt new file mode 100644 index 0000000..3cacfb7 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc6.txt b/malva/ProblemInstances/VRP-instances/vrpnc6.txt new file mode 100644 index 0000000..449fd5c --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc7.txt b/malva/ProblemInstances/VRP-instances/vrpnc7.txt new file mode 100644 index 0000000..1b8aa97 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc8.txt b/malva/ProblemInstances/VRP-instances/vrpnc8.txt new file mode 100644 index 0000000..0383887 --- /dev/null +++ b/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/malva/ProblemInstances/VRP-instances/vrpnc9.txt b/malva/ProblemInstances/VRP-instances/vrpnc9.txt new file mode 100644 index 0000000..1910e87 --- /dev/null +++ b/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/malva/README.md b/malva/README.md new file mode 100644 index 0000000..53d6d5d --- /dev/null +++ b/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/malva/environment b/malva/environment new file mode 100644 index 0000000..2f1eaac --- /dev/null +++ b/malva/environment @@ -0,0 +1,20 @@ +# Malva Configuration. +MALLBA_DIR=/ens/home01/g/gonzalo.menendez/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/malva/inc/Mallba b/malva/inc/Mallba new file mode 120000 index 0000000..5cd551c --- /dev/null +++ b/malva/inc/Mallba @@ -0,0 +1 @@ +../src \ No newline at end of file diff --git a/malva/inc/inc.env b/malva/inc/inc.env new file mode 100755 index 0000000..3976b86 --- /dev/null +++ b/malva/inc/inc.env @@ -0,0 +1 @@ +ln -s ../src Mallba diff --git a/malva/lib/Makefile b/malva/lib/Makefile new file mode 100644 index 0000000..5bacf25 --- /dev/null +++ b/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/malva/lib/libmallba.a b/malva/lib/libmallba.a new file mode 100644 index 0000000000000000000000000000000000000000..aa8b8d0e65e3c1868112f58ce9febe2f4d2c22e2 GIT binary patch literal 34998 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 literal 0 HcmV?d00001 diff --git a/malva/rep/CHC/CHC.cfg b/malva/rep/CHC/CHC.cfg new file mode 100644 index 0000000..0f6c796 --- /dev/null +++ b/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/malva/rep/CHC/CHC.hh b/malva/rep/CHC/CHC.hh new file mode 100644 index 0000000..0c89fe4 --- /dev/null +++ b/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/malva/rep/CHC/CHC.pro.cc b/malva/rep/CHC/CHC.pro.cc new file mode 100644 index 0000000..65672fd --- /dev/null +++ b/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/malva/rep/CHC/CHC.pro.o b/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/malva/rep/CHC/CHC.req.cc b/malva/rep/CHC/CHC.req.cc new file mode 100644 index 0000000..a59f377 --- /dev/null +++ b/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/malva/rep/CHC/CHC.req.o b/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/malva/rep/CHC/CHCstructures.hh b/malva/rep/CHC/CHCstructures.hh new file mode 100644 index 0000000..70aba85 --- /dev/null +++ b/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/malva/rep/CHC/Config.cfg b/malva/rep/CHC/Config.cfg new file mode 100644 index 0000000..b34042e --- /dev/null +++ b/malva/rep/CHC/Config.cfg @@ -0,0 +1,3 @@ +CHC.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.chc.lan.txt diff --git a/malva/rep/CHC/MainLan b/malva/rep/CHC/MainLan new file mode 100755 index 0000000000000000000000000000000000000000..f71c6e405ea5e9ef5a0fe9ad9c3c33807afa6d2a GIT binary patch literal 150656 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%0A{#|8_WyPi?W%6s~sep*?E<?DL`<;BiC za<<($X%MEDTQ|-lXGje(@!Ia}<Wyd;Qy>@H6)*QHoR!q7zEkP^7pH1JB_sj!(W0)# z$klAF7!=99T%G8KF`3)$jCHSUx%#GiCCgyvWcLd1-R@*^MIM-FY<Er|51jMu`Rz`3 z$()4SlHU)UbJ=W>T0Tqg=B-jm(Od1f4*w1~$19;d&KJX!m&h8vlL2erUt|4W%|Fev z8oXx$7f>^eJ8+<ppC$Nn)R~#4%00j$v@`TSOrPLRQ~yL;>uQ?%>Ey^XRX0kRwEj!8 z)qPtcv(?I%+}Y}#oQYxHt`NiQq2@Qj$ZS<Cku6i{*xBlA=2_HUpV{OmX0|#3A~IXe zWR@xoZ8Gj9v(*a-l<PAU&y;kJ^U&|zJX{D#VOoW~({sL=^9I$@<-<kyOQ)b_wA?p6 z;7nbn9Mt*kcQg*C0Pd7c!k>}?MW<}Ho~y+!Hexbm6R}DB+DoFzl+Al>NmY=a2lnWK zOlv1Ek4Z-(tR>y7nF<Y(mSm<vD<+Ec0jF&o7@fnK_lZR3uiw)1R}uZWh@!G_Xxw-u z{fTs_Qsl;;8TSf0pFSzc=|#t%cIf2h-LCN@Y=SN-@c<$6QKSzX-#5rIKP(uaFZ<!0 zOvDB-QR}XKR4rfbMQc$#KN#62c^cWG_5EpS)TY8O68%w|juY>IPK6d5icRJEV{<Jw zb+2U_Y>SW>HenhZ8X}7O-uI9lX$!AQWTwHkc!o@a59UK0YZ{#M?@fbS{~{&fd62g? zHf;vYG&qYJ^m-aR{{=k_uI(4~gwH<LF+RdST#q<j`c&f)3+3ij-PWMGp>F(u=dIm& z@Ob76=6Mi#eno0|rh0};YF=*5s?Q#AAC19e%1PRsGY5e3!%6Ab7M>;-kIhkzx!t+s zbah#3F3a_0xw*VlU#>8hL)GHrv39XEs`~58N)x(7Yi=@^SLn-i=5mC-Y%_5$(3jc+ zwmU(6sU2XuGf-dZHnrV3USBpFRnP0o4d!yAT#}tRI4+(lFXv&x_q=+4i%d4;c>~u} z+DeQS2Z|c2gH9ngOt{6PJ|P8{%d_u}4^G)V{G?1}tjyI*P1A0m5jGgh@%@qQ&Sf%s zHaw>Dwa2+$U+R4Ed^ML0RJSV&G(ILql*OEE2;e%btp1FbHi)^vI<cZNWEZ!b>X^c< z+Jn@@vHLSuZ4>c^$8-hlaZc1}=n7&zESIuiMDv5POq7;#98W?xrwo>mzBm2Sj<k^Z zN)<0Pa$Cr2x#%A9oGb{RGrJq!g(70_c@~Q?3q|%j=C)_%Y$dgyC0!`~<j<r}3z_tm zAXA8cI^Wc@1*f`I)_s|)?oplE9_MFtnXa){-42=G@Uu;-at}Da;LdepfoRIFZ@=rG zpVL+4voc3Q=6%vxtWK1eA!~Qi{zAGwMkBfr?n67jA7P$?{62<IFY?P3iy-)qKj{c} zsZ6WP-uN_>X_K#Apo2G40C&Oq(c5s59^1S)G>pGsZqK^)VTxm(&oEQty(1JAvcgZc zPy|a}WK}0FBoDl#s2MDTI8ln4+o~t<)OykLzM}T?<yAj5+!44w;M7f*8<l+Qh|kMr zK5{s}{z<W(vl3dk{LDuVITa$4`N-DXl<kCz?Q)-?@YcRFBK!Ml&PE&HZG6w3U_S3C z2A(AY0yuyh?zv;PuYA)C1AFs3rEJQ8fv2QL510o?ui;e!dz{14C#u2ayW*uV-;nxH zOf$@0dDhm%Z)2*Vo*d0suIAgVTu1d~e*Y2?UHxtTik?)hN6ld~ocBmuo(asTuHP%q zD7)(`^R;++ky&Bm`aw2jribM5m*xBtU<n^*q)g>Z@lEUB<Mg7`6C2hJDiKL}oM<AS z?_G5RR+6bW?<}Ypl&<pop?WZ%*B8j`MJw_egMD}+W1{Jf_c(8HE#FZ@PiyU^(ly~c zBc%Y(a_dWNv~73Zz$vBo`U%2JLNiu>R{Il1vEHj+ti4m;uaO9qWKHtB;cTSM=paw> zv$%j)zbR>?m*>ehzOPujo;T8EtbPrHQA7KlVLmExmq=W6%{onN6q5A^9mE@px_G}= z=IRG2T--ap)?F$(K5#0p0^{EC_43ux*;ma~3!998*Y=S_D;^^PFW?&bG+9#F`1{A8 zyFNZ%Tx^e{p6+(v4CZ~cRmXVselEV7n1-CZ5A41siIDvT1$;u=i4R}jpmeKkzVpeA zNGu#Eo+a<i(z7F85hgo94c&RImOEFhSs?a^$?r42iO=tOp8URZocPjKro23OyZ835 z#Gsfe`u?&|7x^t`^mp@n?Dg<PY7f%)<xgyBfbM!YD^ncOyB_{2Q^ADwL&AD^0`a6B zZw+|X!^=;h(h}FhmQC>~V9a{>a%9bVxM{yk|2}Xski)lRJ=`ZK24{Zi|6g1Wk5PHv zqt?St|KF-AHNE*O8>3eN=O%T<yKmlB!P(AF#Nnua`Q8wySlh{YJbIPmY}Qw1Exb}+ zv9KNEgg960ZxljIkg^WY$vgLZvJrAV6GxE`63TkGUd@B|$a?tKk0{Hq6x@k(oAq!H z8o6E%->Z56wI1HeX=FY8J1*$>@&|>aQ&^;W6tz0Ok~*e;pl9XzIfOV@%i)VTk1mHZ zh@hgY<?vAV%9dCIxH9YO<4~r=)XF%`6;mtYPwD1W7~Z|z`G70IPMk)JaHi_6xIZA+ z)p|Hp3GHz{JXv{(tcMTK(SFVK@G2bW>#T<-pq&ov$IUk8)3<GowjO?e%zwHbe(T}L zdbpGkNdG$P7S6;le<)RcK+WF|<F1D@&Xn_*yEhY=m|@>O6Uk4^dUzN_WIf!;04VNz zE^aLA;j;*o>l2?6Uag1MBck(gHl)nyMBo<B`L8&4`?!Sl@Og8UgE~LIT;s_UfL5Y@ zc__oh!&0E=+U>?1EjG!B?UG>;v2*6>Xoupi-SzODZMq=mze-+`u7|UvJ(-zS`8gte zz-j#^7@1u$%E?-;A?bSfhayVBZ|MK^*2C{VB+2RZ@QY9A<i5R1V-IYCE-G;kA$kG) zDNmJo*2CTKPKNUM_3&+Ijjo3W-lz4wcxBY4Qmjiwf7GT!#XF!sHezB^xqcThsS2^F zdwulvaPS+VxbF{sY)9I{>k`?!9)52$#Q&l7aLXU0Bzv5a|IrwJ5H#!I^od_*J^VKQ zffukL_qLNNeYf$5i$`((zq1}5FExpI^LTnTvL3#enU!ZfJX!j?Mzh@7?v&_Dz1-UF z6zWS^t4XJLosKIjJGtz2hGg3;2kCFMuwD*sclzkdbw>CU9aolr689{9=`N3Lec7%Y zV7v3^Af;LR$95-GhidoO?tCJ%r^d(J)$)64GPT_);-OHPbYi`)yB;3Pgf@OX{Au^E zy&k?uM$qVbc(K0J2H4}Q<?>%#51;hnvDU-gbsD;Y`2CPvCS4EvPn3|p6?fZ_7Lu?Y ze(r1x`G06Vd@H+`(n8L8Sx_x8`|H_)Gyl=p_3-U<nO&`ie}uopt%pZ(56QD0u1%D< z5D7{9L+SdW>)|I)?P@*z&PzH%y~?!8>@wyvZkv2AsDpn+0o?WQ+tTtQJ@)_G>*2Pu zJnP}=P}24A5@_j@)OvWX$b9Yf@T2LT^>9AzO1hEWzOL89)~}@pk6jP%mp)MqE>+^C z)JIRL55+XWc-O<NOf|gg;TEo=`r_BaA8XBKJ-m~&|K0U)2~+&YdiYCj5dSCZVfmn$ zcRl=ju9L5aAEl2m>)~xUrF4k5BHZ<QxReT!*~hxmkxsrIzJXr;sO#Z55|>)YKf${m z9?W!zZS+qI)P8DZ^nKS!*TZWr5*;5nr8B{}_3)OG=<F+DJv{e*B6PVPz8T9)*1B8| zw-5VQ*TW;oji|i%_<w6X{K(JZ^Xpv?znV&ZkG38Tc9CE2dU*R}y`3_dy5%eDlY3j+ zWi)1kWipEofoy?olSlGDXl?5bGYTSK9{FK@7`dPRjKyOP&R2bSwW*vH)bnQ316*;E zbNTa;`}gW*NyAOHyg=UPObZ~;aJ_sDfUA&P$qjpU5#0TD*<KHyH}(#jH5~ga1@)r_ z)$*$_b^15wN@8sD^(RzrerNOMPtjlh&w~0l9JcqB?U|(MEIFkynVS*GocDhD-o<`N zJMz53>d#hmuV0>CP=DxoKCkn15R*5KUN&6dycz-aH8wY35a(U=Eo|CL=k1N(aEZjN z@5gL9jFh!^Uu?JpF3*TQKNTOYzCm%c_}Hi6rcr8U<vc>(+4bt-PCz8fZ=I#G{Nyl| z<!!*`yCl2cBD>rv6?+liNzW8(?Ydmg`lIFF`&L|j<#vbM)=>71BotG>qAv^eWW}d+ zl8r$+8>4hKW=b}GC)s$Yw^+@S-jlKE&1{@R)$X_X@XPWc8@LPhWo`F{$=RqrzG3Dl zhSh@lcbtFrQi<i@1GbxB^$1n&=fA1SJzNreMiLxPg5+nG4!&OpKLTvtD!~Kd@-v(C zXOe*&$-o4a0bY1d9xlmV{aWq7XdbF{9>!pj406|f`$U-<N&{tAU>CPWNc3LiH>1ze ziQXlNzATCUg17{Sb#Ooj_m|*TC3p?N?*8iDeMe&aOSPxE{ekdJy{#HMeA7s)cG$MO z-qyA}8f;$B+McIdbDnC=<c94AYMI8n3e}bszQC%PqAHZ8?R@kVy=QfnG|A1GDOOQ_ zL*6La7j-7~RFjUMlgqnR6^{PSP-WO!U~?)Zb>2l}VN=8O^oHeGxtmnk8*a+UZ<sPl zsdBDTDl%8G?2^KY3(%BK*J?(Hn(m_J9>l!<zyi~I?e&L&GF;TZ%G(#HhQj)G=K_^P zZHym0sH{2q$ssDcXGl6HNjl#`mTaum!RvMKFM!ScB{+*<*`GA_#j?FEs(X1hU1UmZ z7peM1`p4Cu)f^Y`K-aznjhAHW*F9WFK^mrHuYR%S&(di$OkqFtdRx9`mJu<Mw%gOv zffhR{WTE7;eGjqA>1iK}W9<>|5A-M7x~D|zH@-iSdvoe}+}!$?F<(B<4N4D7>Esh| zHKpO3=;SAl<Yg6|ct`Hdhf{C^o($$fw%(;$RdH|(DMdlU6u!kaB`d%F-P}!*ZRQ8X z&hL7Nw_J8<=ITEok4?<8VD!)UTm9=bg%OWi`K8RGwU?npJ`I1sd9%Cnwr$kUL#kp% zA3jr6U-um9Cr|39CPUXxe#7)p6Xk8nChB1wwSlPrrK3KpqrMDmo-9$v5;fxgl97xj zeCbxvW*GsU-83(m0qqsPL&-3$WTjT}h$tB)N)D0^!F_b_6*{<Fg2zel>jbMePtJTo z45(hfDc(v;&2N~T9$F(ehE+GZm;|HEvgw%e<KyMiQWNzrjJ%fA=@l=p%1Ry?q9gf< zitnZeh-62`hbOvcB<e390?+vI$9d2jLF9XiE#vg7qN<s4Z%2J%$nA%a@0Coys8+kj z8O}xC1e(nK1V;Ez#s8cE-IV{NHx@HC$PS&dx6@ZgVswzM*VCWG$KUNs8vpgf$_$C| zXFfq^mry=Wecq#Enr@czr60Y17RSqXOJcuh{Y>zRtNO`EX1{3t^zufae#HH#`6qe@ z++twsfb$;hP>l@AYoq-Q_p5khaAy50k<KD$I*Z;l^JTc9_oF{llf=x`TX3tJztUaC ze{(K(>BJRuzZU5;q}!Vr$gSU7RR50Y>=vX;lb@SglDYa$@lAL0Nh(>|c>NpFQ)biD z>px`Yx7hhB5iYxwrfTygxYaikheh!Yn&dcnn5=R1OX?|#^Iiuwmy!qPLL%^c25EGj z_CA1SF3Y3dd#}_D{>wosdV`Msv_zjN(bI^I_T4&oi4I;a!Iw$!dub~8DIGjj2miMO z&z0a82v(NG{2989V^GyhoV%oj>Zw<VrCLJxwTa=<<|FYhO$?Vd9tj_t7%pu(5`I!* zxU}I&_~+7=V)G|$HWL1)#BlKd30G@^Cyo(*S7Nxdu}J)D6T_uVMZzyl43{<(2_Ksn zE^Q_feo|t%G>%C4=hA}Q^4BjP74v<8hRLzl_$%{cnKFG$mB&xUuT&4wj2<yieC)ij zz~(A(j|WoJkd!ZuzdyT3#s6t)V*IC7#L*wwD*ord=IbQ>!f5>M-DwKEu1~M)Kt1s@ zP4sy+pW(3(<*(cG)Z&i^iwm}!3F7uV)s$JW#oWJDoozwG1$v=&HCdC*n0v+PiOeEY zdRhIvME4l`@II}W_h-ewUrU}Bknhn-H?vb^uHh!`kG-N3IzqXo*1unr`N-d8UT_xa z7S;2;guHC?SnJ;{Vdm3MFAlhmh{mKZ^PQ>nFGRcj*9)2W$jI@o6e4PYBHorAX9Ovi zy1gLdig}v7h+e|GUh!m{WoH8~?`f!3`Okc0X26+7_6i#Ectwi5U?Yz~VIp6vGf$a? zrJ~&TvyeeGo$6lHurRx*;hI2E!?KK`hV$jO>HN60dxuo2{J3>AtA6=$t9sMN2rA$G z_33{fIYMQyKi+wSZ^Ci<eCDb@5YGEboX-eTuV{RZk~rlmSLQt$Thc@|5i(c(8R^{c zP4dH8pPXhsy*y9k#~95vn$3ohkJIRH#S6W^zP*E}`q#IjSaK&-cknBnyWJ`$>K5#? zoOYq3IHF^>M@Ng%v5ttm_e7OYh8MXLn5Fb`(^i%67P2R`$8Ta>ui)ca%0DU33JGmU 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 literal 0 HcmV?d00001 diff --git a/malva/rep/CHC/MainLan.cc b/malva/rep/CHC/MainLan.cc new file mode 100644 index 0000000..279b550 --- /dev/null +++ b/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/malva/rep/CHC/MainLan.o b/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/malva/rep/CHC/MainSeq b/malva/rep/CHC/MainSeq new file mode 100755 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/malva/rep/CHC/MainSeq.cc b/malva/rep/CHC/MainSeq.cc new file mode 100644 index 0000000..4c291f8 --- /dev/null +++ b/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/malva/rep/CHC/MainSeq.o b/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/malva/rep/CHC/MainWan.cc b/malva/rep/CHC/MainWan.cc new file mode 100644 index 0000000..4ee19e5 --- /dev/null +++ b/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/malva/rep/CHC/Makefile b/malva/rep/CHC/Makefile new file mode 100644 index 0000000..3225d38 --- /dev/null +++ b/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/malva/rep/CHC/res/empty.txt b/malva/rep/CHC/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/malva/rep/GA/Config.cfg b/malva/rep/GA/Config.cfg new file mode 100644 index 0000000..ad19d32 --- /dev/null +++ b/malva/rep/GA/Config.cfg @@ -0,0 +1,3 @@ +newGA.cfg +../../ProblemInstances/ONEMAX-instances/onemax10.txt +res/om10.newga.lan.txt diff --git a/malva/rep/GA/MainLan b/malva/rep/GA/MainLan new file mode 100755 index 0000000000000000000000000000000000000000..9139cd2135314533f6f792eebc342021aadf23e2 GIT binary patch literal 148776 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 ak?{y$jD5&zfAASD|9$%V2m0f;|NjBoc_|VA literal 0 HcmV?d00001 diff --git a/malva/rep/GA/MainLan.cc b/malva/rep/GA/MainLan.cc new file mode 100644 index 0000000..494e82e --- /dev/null +++ b/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/malva/rep/GA/MainLan.o b/malva/rep/GA/MainLan.o new file mode 100644 index 0000000000000000000000000000000000000000..ee952ae0bb50003219493132a90713e762dcd0ae GIT binary patch literal 9192 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 D=++uG literal 0 HcmV?d00001 diff --git a/malva/rep/GA/MainSeq b/malva/rep/GA/MainSeq new file mode 100755 index 0000000000000000000000000000000000000000..8504b21eb5d13bbbcdcb7e5ff175033ebd031fbc GIT binary patch literal 148880 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[@l5HFg1cwMTl?<#Yx;CirV$)a)wXEp5I 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 BnHB&5 literal 0 HcmV?d00001 diff --git a/malva/rep/GA/MainSeq.cc b/malva/rep/GA/MainSeq.cc new file mode 100644 index 0000000..d4a7c14 --- /dev/null +++ b/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/malva/rep/GA/MainSeq.o b/malva/rep/GA/MainSeq.o new file mode 100644 index 0000000000000000000000000000000000000000..7344717638c4bf3e0c1fef3a3f99d7e0e34819fc GIT binary patch literal 8632 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 Jreor5|9^LfMS}nU literal 0 HcmV?d00001 diff --git a/malva/rep/GA/Makefile b/malva/rep/GA/Makefile new file mode 100644 index 0000000..71b1892 --- /dev/null +++ b/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/malva/rep/GA/newGA.cfg b/malva/rep/GA/newGA.cfg new file mode 100644 index 0000000..c7caf7a --- /dev/null +++ b/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/malva/rep/GA/newGA.hh b/malva/rep/GA/newGA.hh new file mode 100644 index 0000000..a6e8c26 --- /dev/null +++ b/malva/rep/GA/newGA.hh @@ -0,0 +1,855 @@ +/********************************************************************************************************* +*** *** +*** 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 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 (); + 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/malva/rep/GA/newGA.pro.cc b/malva/rep/GA/newGA.pro.cc new file mode 100644 index 0000000..dfdd244 --- /dev/null +++ b/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/malva/rep/GA/newGA.pro.o b/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/malva/rep/GA/newGA.req.cc b/malva/rep/GA/newGA.req.cc new file mode 100644 index 0000000..a594684 --- /dev/null +++ b/malva/rep/GA/newGA.req.cc @@ -0,0 +1,412 @@ +#ifndef INC_REQ_newGA +#define INC_REQ_newGA +#include "newGA.hh" +#include <math.h> + +skeleton newGA +{ + + // 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; + } + + 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; + 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() + { + for (int i=0;i<_pbm.dimension();i++) + _var[i]=rand_int(0,1); + } + + double Solution::fitness () + { + 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 + << 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 + { + int i=0; + Rarray<int> aux(sol1.pbm().dimension()); + aux=sol2.array_var(); + + 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]) + { + if (sol.var(i)==1) sol.var(i)=0; + else sol.var(i)=1; + } + } + } + + 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) + { + 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/malva/rep/GA/newGA.req.o b/malva/rep/GA/newGA.req.o new file mode 100644 index 0000000000000000000000000000000000000000..d2797fd78a9bc1c6caecd830ed0d2a68aaab135a GIT binary patch literal 36184 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 literal 0 HcmV?d00001 diff --git a/malva/rep/GA/newGAstructures.hh b/malva/rep/GA/newGAstructures.hh new file mode 100644 index 0000000..d1cbf8a --- /dev/null +++ b/malva/rep/GA/newGAstructures.hh @@ -0,0 +1,53 @@ +#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; +}; + +/*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/malva/rep/GA/res/empty.txt b/malva/rep/GA/res/empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/malva/rep/Makefile b/malva/rep/Makefile new file mode 100644 index 0000000..2b7ed15 --- /dev/null +++ b/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/malva/rep/SA/Config.cfg b/malva/rep/SA/Config.cfg new file mode 100644 index 0000000..c515435 --- /dev/null +++ b/malva/rep/SA/Config.cfg @@ -0,0 +1,3 @@ +SA.cfg +Instance Problem Path +Result File Path diff --git a/malva/rep/SA/MainLan.cc b/malva/rep/SA/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/MainSeq.cc b/malva/rep/SA/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/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/malva/rep/SA/MainWan.cc b/malva/rep/SA/MainWan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/Makefile b/malva/rep/SA/Makefile new file mode 100644 index 0000000..43b74fa --- /dev/null +++ b/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/malva/rep/SA/SA.cfg b/malva/rep/SA/SA.cfg new file mode 100644 index 0000000..290f7e9 --- /dev/null +++ b/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/malva/rep/SA/SA.hh b/malva/rep/SA/SA.hh new file mode 100644 index 0000000..9c7901a --- /dev/null +++ b/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/malva/rep/SA/SA.req.cc b/malva/rep/SA/SA.req.cc new file mode 100644 index 0000000..6532801 --- /dev/null +++ b/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/malva/rep/SA/StopCondition.cc b/malva/rep/SA/StopCondition.cc new file mode 100644 index 0000000..79e3342 --- /dev/null +++ b/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/malva/rep/SA/StopCondition.hh b/malva/rep/SA/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/dnafa/AdjKeys.cpp b/malva/rep/SA/dnafa/AdjKeys.cpp new file mode 100644 index 0000000..730cb58 --- /dev/null +++ b/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/malva/rep/SA/dnafa/AdjKeys.h b/malva/rep/SA/dnafa/AdjKeys.h new file mode 100644 index 0000000..4622352 --- /dev/null +++ b/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/malva/rep/SA/dnafa/AlignedPair.h b/malva/rep/SA/dnafa/AlignedPair.h new file mode 100644 index 0000000..65efd2d --- /dev/null +++ b/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/malva/rep/SA/dnafa/Config.cfg b/malva/rep/SA/dnafa/Config.cfg new file mode 100644 index 0000000..8175e18 --- /dev/null +++ b/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/malva/rep/SA/dnafa/ConsensusBuilder.cpp b/malva/rep/SA/dnafa/ConsensusBuilder.cpp new file mode 100644 index 0000000..64ee8f3 --- /dev/null +++ b/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/malva/rep/SA/dnafa/ConsensusBuilder.h b/malva/rep/SA/dnafa/ConsensusBuilder.h new file mode 100644 index 0000000..324dc6a --- /dev/null +++ b/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/malva/rep/SA/dnafa/ContigBuilder.cpp b/malva/rep/SA/dnafa/ContigBuilder.cpp new file mode 100644 index 0000000..4aa5614 --- /dev/null +++ b/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/malva/rep/SA/dnafa/ContigBuilder.h b/malva/rep/SA/dnafa/ContigBuilder.h new file mode 100644 index 0000000..91736de --- /dev/null +++ b/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/malva/rep/SA/dnafa/LayoutBuilder.cpp b/malva/rep/SA/dnafa/LayoutBuilder.cpp new file mode 100644 index 0000000..f6293fe --- /dev/null +++ b/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/malva/rep/SA/dnafa/LayoutBuilder.h b/malva/rep/SA/dnafa/LayoutBuilder.h new file mode 100644 index 0000000..b143aec --- /dev/null +++ b/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/malva/rep/SA/dnafa/MainLan.cc b/malva/rep/SA/dnafa/MainLan.cc new file mode 100644 index 0000000..2b937bd --- /dev/null +++ b/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/malva/rep/SA/dnafa/MainSeq.cc b/malva/rep/SA/dnafa/MainSeq.cc new file mode 100644 index 0000000..488096d --- /dev/null +++ b/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/malva/rep/SA/dnafa/Makefile b/malva/rep/SA/dnafa/Makefile new file mode 100644 index 0000000..275b857 --- /dev/null +++ b/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/malva/rep/SA/dnafa/OverlapDetector.cpp b/malva/rep/SA/dnafa/OverlapDetector.cpp new file mode 100644 index 0000000..496ef21 --- /dev/null +++ b/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/malva/rep/SA/dnafa/OverlapDetector.h b/malva/rep/SA/dnafa/OverlapDetector.h new file mode 100644 index 0000000..59f38b9 --- /dev/null +++ b/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/malva/rep/SA/dnafa/SA.cfg b/malva/rep/SA/dnafa/SA.cfg new file mode 100644 index 0000000..739dc52 --- /dev/null +++ b/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/malva/rep/SA/dnafa/SA.hh b/malva/rep/SA/dnafa/SA.hh new file mode 100644 index 0000000..c8d6914 --- /dev/null +++ b/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/malva/rep/SA/dnafa/SA.pro.cc b/malva/rep/SA/dnafa/SA.pro.cc new file mode 100644 index 0000000..a89284b --- /dev/null +++ b/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/malva/rep/SA/dnafa/SA.pro.cc1 b/malva/rep/SA/dnafa/SA.pro.cc1 new file mode 100644 index 0000000..3d95a77 --- /dev/null +++ b/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/malva/rep/SA/dnafa/SA.req.cc b/malva/rep/SA/dnafa/SA.req.cc new file mode 100644 index 0000000..153f37c --- /dev/null +++ b/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/malva/rep/SA/dnafa/StopCondition.cc b/malva/rep/SA/dnafa/StopCondition.cc new file mode 100644 index 0000000..2033972 --- /dev/null +++ b/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/malva/rep/SA/dnafa/StopCondition.hh b/malva/rep/SA/dnafa/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/dnafa/Util.h b/malva/rep/SA/dnafa/Util.h new file mode 100644 index 0000000..63792fd --- /dev/null +++ b/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/malva/rep/SA/dnafa/list.h b/malva/rep/SA/dnafa/list.h new file mode 100644 index 0000000..9df841d --- /dev/null +++ b/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/malva/rep/SA/dnafa/pgfileLan b/malva/rep/SA/dnafa/pgfileLan new file mode 100644 index 0000000..d8a0011 --- /dev/null +++ b/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/malva/rep/SA/dnafa/scp.h b/malva/rep/SA/dnafa/scp.h new file mode 100644 index 0000000..5d04aae --- /dev/null +++ b/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/malva/rep/SA/dnafa/sga.cpp b/malva/rep/SA/dnafa/sga.cpp new file mode 100644 index 0000000..0d1a170 --- /dev/null +++ b/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/malva/rep/SA/dnafa/sga.h b/malva/rep/SA/dnafa/sga.h new file mode 100644 index 0000000..dfb28e8 --- /dev/null +++ b/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/malva/rep/SA/maxsat/Config.cfg b/malva/rep/SA/maxsat/Config.cfg new file mode 100644 index 0000000..2d6daf7 --- /dev/null +++ b/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/malva/rep/SA/maxsat/MainLan.cc b/malva/rep/SA/maxsat/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/maxsat/MainSeq.cc b/malva/rep/SA/maxsat/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/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/malva/rep/SA/maxsat/Makefile b/malva/rep/SA/maxsat/Makefile new file mode 100644 index 0000000..0ffc8d9 --- /dev/null +++ b/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/malva/rep/SA/maxsat/SA.cfg b/malva/rep/SA/maxsat/SA.cfg new file mode 100644 index 0000000..f216912 --- /dev/null +++ b/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/malva/rep/SA/maxsat/SA.hh b/malva/rep/SA/maxsat/SA.hh new file mode 100644 index 0000000..26c7864 --- /dev/null +++ b/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/malva/rep/SA/maxsat/SA.pro.cc b/malva/rep/SA/maxsat/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/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/malva/rep/SA/maxsat/SA.req.cc b/malva/rep/SA/maxsat/SA.req.cc new file mode 100644 index 0000000..f3554e7 --- /dev/null +++ b/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/malva/rep/SA/maxsat/StopCondition.cc b/malva/rep/SA/maxsat/StopCondition.cc new file mode 100644 index 0000000..dcd0513 --- /dev/null +++ b/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/malva/rep/SA/maxsat/StopCondition.hh b/malva/rep/SA/maxsat/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/maxsat/pgfileLan b/malva/rep/SA/maxsat/pgfileLan new file mode 100644 index 0000000..a681b21 --- /dev/null +++ b/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/malva/rep/SA/onemax/Config.cfg b/malva/rep/SA/onemax/Config.cfg new file mode 100644 index 0000000..87d424d --- /dev/null +++ b/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/malva/rep/SA/onemax/MainLan.cc b/malva/rep/SA/onemax/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/onemax/MainSeq.cc b/malva/rep/SA/onemax/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/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/malva/rep/SA/onemax/Makefile b/malva/rep/SA/onemax/Makefile new file mode 100644 index 0000000..82415bb --- /dev/null +++ b/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/malva/rep/SA/onemax/SA.cfg b/malva/rep/SA/onemax/SA.cfg new file mode 100644 index 0000000..b6c9399 --- /dev/null +++ b/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/malva/rep/SA/onemax/SA.hh b/malva/rep/SA/onemax/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/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/malva/rep/SA/onemax/SA.pro.cc b/malva/rep/SA/onemax/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/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/malva/rep/SA/onemax/SA.req.cc b/malva/rep/SA/onemax/SA.req.cc new file mode 100644 index 0000000..a327cb3 --- /dev/null +++ b/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/malva/rep/SA/onemax/StopCondition.cc b/malva/rep/SA/onemax/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/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/malva/rep/SA/onemax/StopCondition.hh b/malva/rep/SA/onemax/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/onemax/pgfileLan b/malva/rep/SA/onemax/pgfileLan new file mode 100644 index 0000000..fa76afb --- /dev/null +++ b/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/malva/rep/SA/pgfileLan b/malva/rep/SA/pgfileLan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/malva/rep/SA/pgfileLan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/malva/rep/SA/pgfileWan b/malva/rep/SA/pgfileWan new file mode 100644 index 0000000..2c73753 --- /dev/null +++ b/malva/rep/SA/pgfileWan @@ -0,0 +1 @@ +machine_name number_of_process executable_path login diff --git a/malva/rep/SA/rnd/Config.cfg b/malva/rep/SA/rnd/Config.cfg new file mode 100644 index 0000000..c8bac1a --- /dev/null +++ b/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/malva/rep/SA/rnd/MainLan.cc b/malva/rep/SA/rnd/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/rnd/MainSeq.cc b/malva/rep/SA/rnd/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/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/malva/rep/SA/rnd/Makefile b/malva/rep/SA/rnd/Makefile new file mode 100644 index 0000000..b15a6cd --- /dev/null +++ b/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/malva/rep/SA/rnd/SA.cfg b/malva/rep/SA/rnd/SA.cfg new file mode 100644 index 0000000..1dbac85 --- /dev/null +++ b/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/malva/rep/SA/rnd/SA.hh b/malva/rep/SA/rnd/SA.hh new file mode 100644 index 0000000..6238f6d --- /dev/null +++ b/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/malva/rep/SA/rnd/SA.pro.cc b/malva/rep/SA/rnd/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/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/malva/rep/SA/rnd/SA.req.cc b/malva/rep/SA/rnd/SA.req.cc new file mode 100644 index 0000000..1702a43 --- /dev/null +++ b/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/malva/rep/SA/rnd/StopCondition.cc b/malva/rep/SA/rnd/StopCondition.cc new file mode 100644 index 0000000..f9cfd89 --- /dev/null +++ b/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/malva/rep/SA/rnd/StopCondition.hh b/malva/rep/SA/rnd/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/rnd/pgfileLan b/malva/rep/SA/rnd/pgfileLan new file mode 100644 index 0000000..d85e66e --- /dev/null +++ b/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/malva/rep/SA/vrp/Config.cfg b/malva/rep/SA/vrp/Config.cfg new file mode 100644 index 0000000..510e26d --- /dev/null +++ b/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/malva/rep/SA/vrp/MainLan.cc b/malva/rep/SA/vrp/MainLan.cc new file mode 100644 index 0000000..8949422 --- /dev/null +++ b/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/malva/rep/SA/vrp/MainSeq.cc b/malva/rep/SA/vrp/MainSeq.cc new file mode 100644 index 0000000..41d8a72 --- /dev/null +++ b/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/malva/rep/SA/vrp/Makefile b/malva/rep/SA/vrp/Makefile new file mode 100644 index 0000000..cb3ba14 --- /dev/null +++ b/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/malva/rep/SA/vrp/SA.cfg b/malva/rep/SA/vrp/SA.cfg new file mode 100644 index 0000000..c7ba36e --- /dev/null +++ b/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/malva/rep/SA/vrp/SA.hh b/malva/rep/SA/vrp/SA.hh new file mode 100644 index 0000000..845bb53 --- /dev/null +++ b/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/malva/rep/SA/vrp/SA.pro.cc b/malva/rep/SA/vrp/SA.pro.cc new file mode 100644 index 0000000..43dcaf9 --- /dev/null +++ b/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/malva/rep/SA/vrp/SA.req.cc b/malva/rep/SA/vrp/SA.req.cc new file mode 100644 index 0000000..c14f23a --- /dev/null +++ b/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/malva/rep/SA/vrp/StopCondition.cc b/malva/rep/SA/vrp/StopCondition.cc new file mode 100644 index 0000000..e5a2279 --- /dev/null +++ b/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/malva/rep/SA/vrp/StopCondition.hh b/malva/rep/SA/vrp/StopCondition.hh new file mode 100644 index 0000000..04ef770 --- /dev/null +++ b/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/malva/rep/SA/vrp/pgfileLan b/malva/rep/SA/vrp/pgfileLan new file mode 100644 index 0000000..1c419a1 --- /dev/null +++ b/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/malva/src/Makefile b/malva/src/Makefile new file mode 100644 index 0000000..b6d64fb --- /dev/null +++ b/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/malva/src/Matrix.hh b/malva/src/Matrix.hh new file mode 100644 index 0000000..cc30ae7 --- /dev/null +++ b/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/malva/src/Messages.h b/malva/src/Messages.h new file mode 100644 index 0000000..e46b1d8 --- /dev/null +++ b/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/malva/src/Rarray.h b/malva/src/Rarray.h new file mode 100644 index 0000000..5d1a1c2 --- /dev/null +++ b/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/malva/src/Rlist.h b/malva/src/Rlist.h new file mode 100644 index 0000000..f561d0b --- /dev/null +++ b/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/malva/src/States.cc b/malva/src/States.cc new file mode 100644 index 0000000..f36d197 --- /dev/null +++ b/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/malva/src/States.hh b/malva/src/States.hh new file mode 100644 index 0000000..e3a215f --- /dev/null +++ b/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/malva/src/States.o b/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/malva/src/mallba.hh b/malva/src/mallba.hh new file mode 100644 index 0000000..e022ff8 --- /dev/null +++ b/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/malva/src/netstream.cc b/malva/src/netstream.cc new file mode 100644 index 0000000..932e89e --- /dev/null +++ b/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/malva/src/netstream.hh b/malva/src/netstream.hh new file mode 100644 index 0000000..5c24a3d --- /dev/null +++ b/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/malva/src/netstream.o b/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/malva/src/random.hh b/malva/src/random.hh new file mode 100644 index 0000000..ae6bde6 --- /dev/null +++ b/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/malva/src/time.hh b/malva/src/time.hh new file mode 100644 index 0000000..2dcb9a7 --- /dev/null +++ b/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/malva/stat/file_stat_aco b/malva/stat/file_stat_aco new file mode 100755 index 0000000..8426ce4 --- /dev/null +++ b/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/malva/stat/file_stat_pop b/malva/stat/file_stat_pop new file mode 100755 index 0000000..8512575 --- /dev/null +++ b/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/malva/stat/file_stat_pso b/malva/stat/file_stat_pso new file mode 100755 index 0000000..672f857 --- /dev/null +++ b/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/malva/stat/file_stat_sa b/malva/stat/file_stat_sa new file mode 100755 index 0000000..d006462 --- /dev/null +++ b/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/malva/uml-comun.gif b/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